Ревью rust: перенос в вики не должен удалять из репозитория то, что нужно агенту для работы (бэклог, статус, планы, код-стайл, спеки). Дублирование вики и репы разрешено и обязательно: вики — актуальные версии для людей, docs/ — зеркало для контекста агентов. README разведён по ролям.
258 lines
23 KiB
Markdown
258 lines
23 KiB
Markdown
# Дейл (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-аккаунт на тенанта; несколько аккаунтов — позже (схема готова).
|