Files
Deal/docs/spec/ТЗ-дейл-новая-архитектура.md
T
Rustam Khalimov 27c7831910
ci / build-test (push) Canceled after 0s
Deal — единая кодовая база
SaaS-мониторинг Telegram: ядро (модули Cards/Kanban/Pipeline/Tenants/Settings/
Discovery, Api, Infrastructure), сервисы telegram/ai/ml/storage, фронт Vue,
контракты и grpc-hosting, деплой-конфиги (dev/prod/observability/CI-раннер),
Gitea Actions CI, документация (ТЗ, техдок, api-map, код-стайл, планы, бэклог).

Текущее состояние: все этапы роадмапа 0–12 закрыты, сборка 5 sln 0/0,
тесты 1340/130/52/38/9 зелёные.
2026-09-11 23:56:47 +03:00

258 lines
23 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Дейл (Deal) — Техническое задание на новую архитектуру
> Версия: 1.0 (отражает этапы 0–12)
> Дата: 2026-09-10
> Связанные документы: `docs/architecture/2026-09-05-deal-architecture-design.md`,
> `docs/architecture/2026-09-10-unified-api-contract.md`,
> `docs/architecture/2026-09-10-operator-analytics-contract.md`,
> исходное ТЗ прототипа LeadRadar V1.2 — `archive/leadradar-legacy/ТЗ-LeadRadar-v1.2.md`.
---
## 1. О продукте
«Дейл» — SaaS-сервис мониторинга Telegram-каналов и групп. Клиент подключает свой
Telegram-аккаунт, выбирает каналы/группы для мониторинга, а система:
1. получает сообщения из источников в реальном времени;
2. отсеивает мусор: рекламу, скам, служебные сообщения, дубликаты, устаревшее;
3. структурирует оставшееся в **карточки** (заказ/вакансия/услуга) по профилю клиента
(сфера, стек, бюджет, локация);
4. раскладывает карточки по **колонкам-фильтрам** клиента;
5. обучается на действиях клиента (ML) и всё больше обрабатывает поток сама;
6. помогает искать и подключать новые источники (Discovery).
**Целевая аудитория:** специалисты и мастера в разных сферах (разработчики, дизайнеры,
риелторы, строители и т.д.), которые ищут реальные заказы и клиентов в Telegram.
**Ключевая ценность:** видеть реальные заказы и клиентов, а не кучу дубликатов и рекламы.
---
## 2. Термины
- **Тенант** — клиент SaaS. Владеет схемой БД, настройками обработки, ML-моделью.
- **Аккаунт (Telegram)** — личный Telegram-аккаунт тенанта, подключённый к системе.
- **Источник** — откуда система получает записи. Сейчас это Telegram-канал/группа/чат (тема форума);
контракт источника универсален, поэтому позже сюда добавляются другие сервисы (WhatsApp, сайты,
файлы/таблицы) без изменения ядра.
- **Сырое сообщение** — оригинальное сообщение из источника до обработки (входные данные пайплайна).
- **Карточка** — единая сущность системы: ядро (id, заголовок, источник) + опциональные модули
(содержимое, бюджет, контакты, атрибуты, комментарии, ссылки, файлы, ТЗ, история, напоминания,
размещение в контейнере). Создаётся из прошедшего фильтры сообщения либо вручную; переезжает между
дашбордами/контейнерами без смены сущности. Термин «лид» не используется — это лишь входное сообщение.
- **Источник (Source)** — откуда пришла карточка: локально/вручную, ссылка на сайт, файл, Telegram
(канал/группа/чат, тема форума), колонка импортированных данных, внешний API, ИИ (провайдер+модель),
составной «первоисточник + цепочка обработки».
- **Контейнер** — общая база колонок/стадий/зон: пользовательские колонки дашборда (набор фильтров),
стадии «Выбранных», «Неразобранное», архив, корзина, терминальные зоны. У каждого контейнера —
политика (что можно/нельзя, автоочистка, терминальность).
- **Отсев** — сообщения, отклонённые пайплайном (с причиной).
---
## 3. Роли и доступ
| Роль | Возможности |
|---|---|
| **Оператор (владелец SaaS)** | Создаёт тенантов и инвайты; управляет лимитами; видит health; impersonation с аудитом |
| **Тенант (клиент)** | Входит по инвайту, задаёт пароль; подключает свой Telegram-аккаунт; настраивает обработку; работает с дашбордом |
- Регистрация — **только по инвайту** (ссылка/код от оператора).
- Логин: email + пароль; email уникален в масштабе SaaS; `tenantId` — в сессии/JWT.
- Вход оператора — отдельный, изолированный от тенантов.
---
## 4. Подключение Telegram-аккаунта
1. Оператор один раз задаёт ключи приложения Telegram (`api_id`/`api_hash`) — глобально.
2. Тенант в UI: «Добавить аккаунт» → QR-код (или телефон + код подтверждения).
3. Система сохраняет сессию аккаунта (в telegram-service) и показывает статус подключения.
4. **1 аккаунт на тенанта** на старте (схема допускает расширение).
5. При первом подключении система подтягивает список диалогов аккаунта (каналы/группы/чаты)
и обновляет его при каждом входе на экран каналов и в фоне (появление/исчезновение
источников отслеживается автоматически).
### Мониторинг источников
- Тенант включает/выключает мониторинг по каждому источнику из списка его диалогов.
- Настройка «новый чат → мониторинг автоматически» (вкл/выкл).
- Источники, удалённые/покинутые вне системы, исчезают из списка.
- Кнопка «Перечитать»: догон последних ~10 сообщений всех включённых источников
(с паузами, анти-бан).
- Полученные сообщения **сразу помечаются прочитанными** в Telegram.
### Discovery (поиск и подключение источников)
- Тенант создаёт **задачу поиска**: описание цели → ИИ генерирует ключевые слова.
- Система ищет каналы/группы/форумы, в которых аккаунт **не состоит** (глобальное правило).
- Каскад фильтров: участники → язык → содержание (по темам, порог ≥40%).
- Кандидаты показываются «на рассмотрение» с метаданными (тип, участники, fit «X из N»,
темы форума, метки: закрытая группа и т.п.).
- Действия: «Вступить и мониторить» (вручную) или авто-вступление с квотами
(50/сутки общий, паузы 50–70 с), «Отклонить» → чёрный список.
- Чёрный список исключает источник во всех задачах; снимается вручную.
---
## 5. Обработка входящих (пайплайн)
Путь сообщения: **источник → очередь → стоп-лист → дедуп → ML → ИИ → карточка**.
Всё, что отсеяно, — в «Отсеве» с причиной. Настройки обработки — **per-tenant**.
### Этап 1 (без ИИ, дёшево)
1. Минимальная длина текста.
2. **Стоп-фразы** (настраиваемый список).
3. Отсев резюме соискателей (настройка).
4. Тип заявки (только вакансии / только заказы) по контексту.
5. **Дедуп**: одинаковый текст (нормализованный хэш) уже в системе → отсев «повтор».
6. Устаревшее сообщение (старше срока архивации) → отсев.
### ML-слой
- Если ML-модель тенанта уверена — решает сама: спам → отсев; колонка → карточка сразу.
- Не уверена → сообщение уходит на ИИ.
- Возврат из отсева (force) идёт мимо ML к ИИ-классификации.
### ИИ-слой (если включён)
- ИИ-фильтр: сообщение не про заявки/интересы тенанта → отсев.
- Классификация: структурированный разбор (компания, формат, о задаче, требования,
плюсы, условия, бюджет, стек, контакты, тип заявки).
- Назначение колонки с проверкой её правил.
### Глобальные фильтры
- «Не создавать карточку без суммы» — отдельно для вакансий и для заказов.
- Исключения по ключевым словам/технологиям/бюджету/локации (стоп на уровне фильтров).
### Карточка
- Единая сущность: ядро (id, заголовок, источник) + опциональные модули. Вид карточки — композиция
модулей, не отдельный класс/таблица; третий дашборд работает с той же карточкой.
- Реализация (этап 9): карточка — **одна строка одной таблицы `Cards`** во всех дашбордах; таблица
`ProjectCards` упразднена. Модули — колонки той же строки (`StackJson`/`LinksJson`/`FilesJson`/
`HistoryJson`/`TzText`/напоминание), комментарии — общая таблица `LeadComments`. Колонки/стадии/зоны —
единый реестр контейнеров; пространства не пересекаются (карточка не может быть одновременно
в дашборде и в «Выбранных»), «взять в работу» — смена контейнера, а не клон.
- Модули: содержимое (единая структура «О заявке»: Компания → Формат → О задаче → Требования →
Будет плюсом → Условия), бюджет (from/to/валюта), контакты (квалифицированные: tg/phone/email/
linkedin/site), атрибуты (стек/грейд/локация/сроки — настраиваются тенантом в UI, не зашиты),
комментарии, ссылки, файлы, ТЗ, история движения, напоминание, размещение в контейнере.
- Исходное сообщение карточки хранится и доступно: текст структурируется и показывается в карточке,
вложения/ссылки/контакты — отдельными блоками; кнопка «Обновить из источника» догружает оригинал
у сервиса-владельца источника (для Telegram — по id сообщения), если он доступен.
---
## 6. Дашборд (канбан)
- Колонки: «Неразобранное», пользовательские колонки (набор фильтров), «Архив», «Корзина».
- Пользовательские колонки создаёт пользователь; ИИ может **предлагать** колонки с
обоснованием (по каким критериям), пользователь принимает/отклоняет/переименовывает.
- Колонка = сложный набор опциональных фильтров: ключевые слова/стек/грейд/уровень/цена/
бюджет/локация/тип + отрицательные фильтры («чтобы не попадало»).
- При помещении карточки в колонку указывается, **по каким критериям** она попала.
- Карточки в колонке: свежие сверху. Drag&drop между колонками (с обучением ML).
- Быстрые действия на карточке: комментарий, корзина, контакт, «открыть исходник».
- Виджеты-счётчики свёрнутых колонок; колонки можно двигать, менять размер/ширину.
- **Архив**: карточки старше N дней (настройка 1–30); очистка архива через 90 дней.
- **Корзина**: очистка раз в 7 дней; из архива/корзины карточку можно вернуть (на канбан).
### «Выбранные» (пространство стадий)
- То же пространство карточек: **те же карточки** в контейнерах-стадиях
(Запланировано → Отклик → Согласование → В работе → Проверка → Готово / Отложено и др.).
«Взять в работу» — переход карточки в контейнер, а не создание второй сущности.
- У карточки наполняются модули работы: комментарии, изменение суммы/стека/контактов,
прикрепление ссылок, ТЗ, **файлов** (медиа/документы; тип определяется автоматически;
хранение в S3/MinIO; на карточке значки количества файлов и ссылок).
- Отложенные: напоминания (через срок + в заданное время, выбор даты в календаре);
настройка в общих настройках; если напоминания выключены — окно не показывается и
установленные не срабатывают.
- История движения карточки (статус, дата, время) — под спойлером в карточке.
- Ручное создание карточки с тем же набором полей (пометка «создано локально»).
- В архив/корзину дашборда карточки «Выбранных» не попадают; свои терминальные зоны:
«Отклонено», «Выполнено» (политики контейнеров).
---
## 7. Вкладка «Обработка»
- **Очередь**: сырые сообщения, ожидающие обработки (этап 1 / ожидают ИИ), с автопрокруткой.
- **Отсев**: отклонённые сообщения с причиной и источником решения
(правила / ML / ИИ / система), включая конкретное стоп-слово/фразу.
- У записи: метаданные (источник, подпись, вид, время), «показать исходное сообщение» с форматированием,
кнопка обновления исходника у сервиса-владельца источника.
- Поиск по отсеву — полнотекстовый.
- Возврат из отсева в обработку: причины отсева игнорируются, ML/ИИ обучаются на решении;
можно указать причину возврата.
- Автоочистка отсева: раз в 3 дня; ручная очистка.
- Вкладка показывает счётчик обработки (в боковой панели отсев не показывается).
---
## 8. Настройки тенанта
- Telegram: ключи приложения (оператор), подключение аккаунта, авто-мониторинг новых.
- ИИ: провайдер (один; включая локальные), модель, ключ (хранится зашифрованно),
промпты (базовый + свой), библиотека готовых промптов по сферам + «мои промпты»,
вкл/выкл ИИ, вкл/выкл ИИ-фильтр.
- ML: вкл/выкл, обучение на действиях, проверка на сообщении/канале, сброс, самооценка
(«ML справляется с последними N сообщениями — ИИ можно отключить»).
- Обработка: стоп-фразы, длина, резюме, тип заявки, домен/ключи, маркеры найма/заказа.
- Проверка текста: сухой прогон по цепочке (стоп-правила → глобальные исключения → ML → ИИ →
«без суммы») без создания карточки — показывает этапы, причину отсева и куда попала бы карточка.
- Колонки: набор, правила, отрицательные фильтры, исключения.
- Валюта: целевая валюта отображения, источник курсов (4 запроса/сутки), конвертация
при приходе данных + пересчёт старых карточек (кроме архива/корзины); USDT = USD.
- Хранение: срок архивации (1–30 дней), очистка архива/корзины.
- Уведомления и напоминания (общие; отложенные — отдельно).
- Звук, внешний вид.
---
## 9. Лимиты (бюджет токенов)
- Каждый тенант имеет **бюджет токенов** на LLM-вызовы (период — настраивается).
- ai-service оценивает каждый вызов в токенах и списывает с бюджета.
- При исчерпании: AI-обработка переключается на fallback (ML/локальный разбор),
тенант получает уведомление; приём и базовая обработка сообщений не блокируются.
- Оператор видит расход по тенантам в админке и может менять бюджет.
---
## 10. Админка оператора
- Тенанты: создание, инвайты, статус, лимиты/бюджеты, приостановка.
- Health всех сервисов и очередей.
- Аудит: входы/выходы, инвайты, impersonation, действия оператора и пользователей тенанта
(создание/перенос/удаление карточек, комментарии, контейнеры, настройки, каналы).
- Аналитика: расход токенов (по дню/тенанту/провайдеру/модели) и лента действий с фильтрами.
- Подозрительная активность (по логам безопасности) и метрики сервисов (Prometheus/Grafana).
- UI: оператор-консоль (`#/operator`) и страница активации инвайта (`#/join`).
---
## 11. Нефункциональные требования
- **Безопасность**: TLS, mTLS между сервисами, параметризованный SQL, защита от
IDOR/XSS/SSRF/CSRF, Argon2id, rate limiting (прокси + приложение; счётчики — распределённые,
в БД, работают при нескольких инстансах), Cloudflare.
- **Надёжность**: ежедневные бэкапы (Postgres, файлы, сессии), outbox для событий;
авто-очистки (retention аудита, лимитов, окон rate-limit); мгновенный разлогин suspended-сессий.
- **Наблюдаемость**: структурированные логи → Loki, метрики (OpenTelemetry → Prometheus) → Grafana
+ правила алертов; история расхода токенов (`token_usage_events`).
- **Масштабируемость**: модульный монолит + отдельные сервисы (ml/ai/telegram);
горизонтальное масштабирование сервисов; k8s — позже.
- **Производительность**: пайплайн обрабатывает поток без потерь; анти-бан-паузы
Telegram не блокируют обработку.
- **Локализация (i18n)**: весь интерфейс — на русском; все пользовательские строки вынесены в ресурсы
(без хардкода в компонентах), включая тексты ошибок; фолбэк — русский. Переключатель языка и второй
язык — **в бэклоге**: делаем, когда возникнет потребность (основа в ресурсах уже готова).
Область — основное приложение и оператор-консоль. (Этап 11 roadmap.)
---
## 12. Ограничения и допущения
- Фронтенд (Vue 3 + Vite + Tailwind) переезжает из LeadRadar; с этапа 9 контракт карточек/колонок — единый
(`/api/cards` + `/api/containers`, см. `docs/architecture/2026-09-10-unified-api-contract.md`).
- Данные текущего LeadRadar тестовые — не мигрируются.
- Kafka, k8s, биллинг-провайдер, саморегистрация — вне рамок текущего этапа.
- 1 Telegram-аккаунт на тенанта; несколько аккаунтов — позже (схема готова).