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 зелёные.
20 KiB
Дейл (Deal) — Roadmap этапов (все этапы 0–7 выполнены; 2026-09-08)
Исторический документ (roadmap этапов 0–7, 2026-09-08). Актуальное состояние —
docs/superpowers/STATUS.mdиdocs/technical/Техническая-документация-Дейл.md.
Назначение: зафиксировать план продолжения разработки «Дейл» по этапам. Каждый этап исполняется как отдельный SDD-план (файл в
docs/superpowers/plans/, ledger в.superpowers/sdd/<plan>/), задача-за-задачей с ревью. Проект НЕ git — фиксация в отчётах и ledgers.
Выполнено
-
Этап 0 — Каркас (
2026-09-05-deal-scaffold.md): структураsrc/, фронт переехал вsrc/frontend/,.editorconfig+Directory.Build.props,Deal.sln(11 проектов), тесты, dev-Postgres (:5433), tenant-контекст (TenantId/ITenantContext/TenantContextAsyncLocal/ConnectionStringProvidersearch_path), EF (public),TenantSchemaMigrator, CI-скрипты. -
Этап 1 — Доступ и мультитенантность (
2026-09-05-deal-stage1-tenancy.md): карта/api(docs/api/api-map.md, 101 эндпоинт, 87 использует фронт), два DbContext (системныйpublic+ бессхемный tenant: таблицаsettings), миграции InitialSystem/InitialTenant, модуль Tenants (порты+адаптеры, Argon2id, сессии 30 дней), auth-эндпоинты 1:1 (login/logout/me/change-password), SessionMiddleware +ITenantContext.Reset,TenantProvisioningService(схемаtenant_<32hex>+ Migrate cMigrationsHistoryTable("__TenantMigrationsHistory", schema)),TenantBootstrapService(seed: тенант id000…001+ admin/admin из env; идемпотентно). 25 тестов PASS. -
Этап 2 — Settings (настройки тенанта) (
2026-09-05-deal-stage2-settings.md): модульDeal.Modules.Settings(каталог ключей/дефолты 1:1 с прототипом, ISettingsStore, SettingsService снимок+PATCH 1:1, IncomingRules, PromptFiller, RatesService) + адаптеры (SettingsStore наsettings, AesGcmSecretCipher), эндпоинты GET/PATCH/api/settings, POST/api/ai/check, GET/api/rates, POST/api/rates/refresh,/api/ml/*(заглушка LocalMlClient), POST/api/admin/check-message(тестер фильтров). Секреты AI/Telegram — AES-GCM (enc:в БД, ключ envDEAL_ENCRYPTION_KEY/файл). Задачи 1–11 приняты: 175 unit-тестов PASS, build 0/0, сквозная curl-приёмка :5080 PASS=60 FAIL=0 + psql (шифрование, внутренние ключи не публикуются). Ограничение: Settings-экран обслуживается бэкендом, но Vue-фронт полностью оживает только с этапом 3 (егоboot()требует/api/boards,/api/leads,/api/projects,/api/tg/status,/api/columns/state; Telegram-вкладка, кнопки «Проверить правила сейчас»/«Пересобрать индекс», «Предложить ключи» и канбан-фронт — этапы 3–6). -
Этап 3 — Kanban (дашборд): колонки, карточки, архив/корзина (
2026-09-05-deal-stage3-kanban.md): миграция TenantKanban (Boards/Cards/LeadComments/CardMoves/MlOutbox в схеме тенанта), модульDeal.Modules.Kanban(доски/карточки/правилаColumnRulesс matchHits, StorageTickService + фоновый StorageTickScheduler 30 с, ConversionRecomputer, демо-фабрика, эвристика ИИ-предложений), эндпоинты boards/columns/leads/search/events(SSE)/admin/demo/ai-suggest, boot-заглушки /projects и /tg/status, LocalMlClient+PushAsync. Задачи 1–15 приняты: 410 unit-тестов PASS, build 0/0, сквозная curl-приёмка :5080 PASS=94 FAIL=0 + psql. Ограничения: pipeline/очередь/отсев/FTS — этап 4; projects/файлы/reminder_due — этап 5; реальные ai/telegram/ml и discovery — этап 6; reclassify и /admin/fts/rebuild — контракт-заглушки. Фронт теперь boot'ится полностью и канбан-дашборд работает на демо-данных (реальные данные появятся с pipeline этапа 4). -
Этап 4 — Pipeline + вкладка «Обработка» (
2026-09-05-deal-stage4-pipeline.md): миграция TenantPipeline (QueueItems/RejectedItems/DedupEntries + FTS-колонки SearchTsv на Cards/RejectedItems), модульDeal.Modules.Pipeline(ядро разбора 1:1, Ingest/ProcessingService/PipelineWorkerService pump 1:1, CardComposer черезIKanjStore.AddCardAsync, dedup-связь), портIAiClassifier+ детерминированныйLocalAiClassifier, эндпоинты/api/pipeline/*+ демо-ingest, реальные admin/tick и admin/fts/rebuild (+SSE new_lead/тост очистки отсева), фоновые PipelineWorkerScheduler (2 с) и purge-отсева 3 дня в StorageTickScheduler, FTS-поиск/api/search. Задачи 1–13 приняты: 535 unit-тестов PASS, build 0/0, сквозная curl-приёмка :5080 (Task 13 — финал) PASS=74 FAIL=0- psql. Ограничения: projects/reminder_due/файлы — этап 5; реальные ai/telegram/ml-сервисы и их gRPC-ингресс, discovery, ИИ-предложения колонок на реальных данных — этап 6; оператор/лимиты/ аудит — этап 7. Вкладка «Обработка» и канбан-дашборд работают на реальном конвейере (демо-ingest до telegram-этапа 6).
-
Этап 5 — Projects («Выбранные»): стадии, напоминания, файлы/ссылки, история (
2026-09-05-deal-stage5-projects.md): миграция TenantProjects (ProjectCardsс partial UNIQUE LeadId), модульDeal.Modules.Projects(стадии ProjectStages 1:1, ProjectsService: take из дашборда с уходом лида вcol='taken'/ручное создание/patch presence-aware/move+история/clear-rejected/ комментарии/ссылки; ProjectReminderService; ProjectFilesService), портIFileStorage+ адаптерыLocalFileStorage/MinioFileStorage(deal-minio в compose.dev.yml), эндпоинты/api/projects*(16 шт., файлы и напоминания включены), boot-заглушка /projects снята, напоминания в admin/tick + фоновый 30-с цикл StorageTickScheduler + SSEreminder_due. Задачи 1–13 приняты: 620 unit-тестов PASS, build 0/0, сквозная curl-приёмка :5080 (Task 13 — финал) PASS=75 FAIL=0 + psql (take- семантика, история, clear-rejected, UNIQUE LeadId, файлы на диске, reminder_due фоновым циклом). Ограничения: реальные ai/telegram/ml-сервисы и их gRPC-ингресс, discovery, telegram-вкладка и/tg/status— этап 6; оператор/лимиты/админка, мульти-аренда MinIO-бакетов — этап 7. -
Этап 6 — Сервисы telegram/ai/ml (отдельные процессы) + Discovery (
2026-09-05-deal-stage6-services.md): gRPC-контракты вsrc/contracts/*.proto(общийDeal.Proto); три автономных процесса — telegram-service (:5101: ферма сессий 1 акк/тенант, QR-вход, AES-GCM-сессии/data/sessions, диалоги/мониторинг/backfill с анти-бан-паузами), ai-service (:5102: LLM-фасад OpenAI-совместимых+Anthropic, Filter/Classify/ GenerateKeywords/EvaluateFit, usage), ml-service (:5103: инкрементальный наивный Байес 1:1 с pythonmlservice/model.py, SQLite на тенанта); core — gRPC-ингресс telegram :5082 (PushMessage→очередь, SyncDialogs, ReportStatus→SSE), модуль Telegram (Dialogs/TgMessages) + эндпоинты /api/tg (14 шт., реальный статус, QR-SVG) вместо boot-заглушки, ai/ml-gRPC-адаптеры за флагамиServices:*:UseLocal(код-дефолт Local, compose.dev.yml — false), MlOutboxFlushScheduler (10 с), модуль Discovery (воркер 5 с: поиск/ каскад оценки/авто-join с квотами и бан-гардом; /api/discovery 13 шт.); полный dev-стек —deploy/compose.dev.yml(postgres/minio/3 сервиса/core, secrets, healthcheck), smoke-скриптscripts/dev-smoke.sh(отложенный живой прогон — Docker Desktop был выключен). Задачи 1–20 приняты: 830 unit-тестов PASS, build 0 warnings / 0 errors всех четырёх sln, curl-приёмки Task 14 (/api/tg PASS=20 FAIL=0) и Task 19 (/api/discovery PASS=37 FAIL=0), in-proc gRPC-приёмки. Ledger:.superpowers/sdd/deal-stage6-services/. Ручные проверки (с кредами): Telegram-вход (api_id/api_hash/QR) и реальные LLM-вызовы; живой smokescripts/dev-smoke.sh— после поднятия Docker. Ограничения этапа 6 (переходят в этап 7): mTLS-сертификаты и prod-compose; лимиты/бюджеты токенов (учётaiTokenUsageуже есть); оператор/админка/аудит-поток; rate limiting gRPC; экспорт/импорт ML-моделей; ротация/бэкап ключей сессий; reclassify на реальном ИИ (контракт-заглушка остаётся). -
Этап 7 — SaaS-контур (Tasks 1–16, 2026-09-08) (
2026-09-05-deal-stage7-saas.md): оператор (public-таблицы, кукаdeal_operator_session, bootstrap env, ручки/api/operator/*— API-only), инвайты + активацияPOST /api/join, лимиты ИИ-бюджета с fallback-декораторами и SSE-тостами, append-only аудит-поток, rate limiting (приложение + gRPC-ингресс + защита входа), Origin-проверка/ security-заголовки/ForwardedHeaders, mTLS за флагом DEAL_MTLS_* +scripts/mtls-certs.sh, Serilog JSON во всех 4 процессах, prod-деплойdeploy/compose.prod.yml(caddy 80/443, mTLS-env, healthcheck'и grpc_health_probe, профиль observability: promtail/loki/grafana) +deploy/.env.prod.example, бэкапыscripts/backup.sh/restore.sh(+deal-backup-lib.sh). Task 16 (финал): актуализированы техдок §5/§7–§11/§13 (фактический стек, Manual-пометки), api-map (раздел «Реализовано в Deal»), user-guide, STATUS.md (этапы 0–7 = 100%). Финальный прогон: core 1123/1123 PASS, telegram 114/114, ai 50/50, ml 36/36 PASS, build 0/0 всех четырёх sln,compose.prod.yml configrc=0,sh -nскриптов rc=0. Ledger:.superpowers/sdd/deal-stage7-saas/. Manual (нужен docker/живые креды): применение system-миграции + сквозная SaaS-curl-приёмка, подъём compose.prod и dev-smokescripts/dev-smoke.sh, mTLS-рукопожатие контейнеров, реальные Telegram/LLM-вызовы, прогонscripts/backup.shи restore-тест — чек-лист в task-16-report.md.
Эталонные конвенции (уже в коде — их придерживаться дальше)
- Модуль = чистый проект (SharedKernel/Contracts): порты (интерфейсы) + record-DTO, без EF.
Регистрация:
AddTenantsModule()(модуль), адаптеры EF — вDeal.InfrastructureчерезAddDealPersistence()(scoped). HTTP-эндпоинты — вDeal.Api/Endpoints/*(MapXxxEndpoints). - Два EF-контекста: системный (public, явная схема) и tenant (бессхемный; новые таблицы модулей —
DbSet в
TenantDbContext+dotnet ef migrations add X --context TenantDbContext; применяются провижинером ко всем схемам). Ошибки API —{detail}; JSON camelCase; кукаdeal_session. - Константы/настройки:
IOptions<T>; без магических чисел; 1 тип=1 файл; XML-doc на public.
Следующие этапы (после этапов 0–7; порядок из архитектуры §12.5)
Актуальный источник отложенного и техдолга —
backlog.mdв корне (роудмап черпается оттуда). Ниже — историческая секция роудмапа.
Этапы 0–7 выполнены (см. «Выполнено»). Ниже — следующие инкременты: заделы этапа 7 (сознательно вынесены, подробно — техдок §11) и пункты архитектуры, не входившие в этапы.
Этап 8+ — следующие инкременты (заделы этапа 7, подробно — техдок §11):
- Этапы 8–10 выполнены (2026-09-10): ревью/качество; единая карточка (unified card); оператор-консоль + активация инвайта (UI) + аудит действий и аналитика расхода токенов + ELK/Loki-дашборды.
- Остаются заделы: OTel-метрики/Prometheus и дашборды метрик (сейчас Serilog-логи → Loki); multi-instance rate-limit и бэкенд попыток входа; экспорт/импорт ML-моделей; reclassify на реальном ИИ; мультиаккаунтность Telegram; биллинг/планы; k8s/Cloudflare-конфигурация; purge-автоматика audit_log.
Этап 11 — Локализация интерфейса (i18n)
Требование владельца (2026-09-10). Весь интерфейс — на русском; все тексты вынесены в ресурсы, чтобы можно было добавлять новые языки и менять язык на лету.
- Русский — язык по умолчанию. Все пользовательские строки UI (экраны, кнопки, подписи, пустые состояния, подсказки, подтверждения, уведомления/тосты, страницы оператора и активации) — на русском.
- Никакого хардкода строк в компонентах. Все тексты — в словарях ресурсов (ключ → значение),
включая сообщения об ошибках, которые сейчас формируются на бэке (
{detail}), — они должны быть локализуемы (ключ + параметры) или переводимы по коду. - Переключение языка на лету, без перезагрузки страницы; выбранный язык сохраняется (localStorage/настройки).
- Расширяемость: добавление нового языка = новый файл словаря, без правок компонентов.
- Форматирование дат/времени/чисел/валют — через i18n-форматтеры (не вручную), плюрализация — через правила языка.
- Ключи — стабильные, сгруппированные по областям (nav/cards/settings/operator/…); отсутствующий ключ в языке → фолбэк на русский.
- Бэк: ответы API остаются с
{detail}/кодами; фронт отображает локализованный текст по коду/ключу (при необходимости — расширяемый словарь ошибок).
UI-область, к которой это применяется: основное приложение (дашборд, «Выбранные», настройки, каналы, обработка) и оператор-консоль (этап 10).
Открытые точки согласования (накопились к концу этапа 1)
Решения владельца (2026-09-06): 1 — бренд меняем (сделано точечно: index.html, LoginView, Sidebar, DiscoveryView, SettingsView); 2 — инвайты/оператор остаются на SaaS-этап, dev-seed admin/admin; 3 — PascalCase — конвенция БД; 4 — кука
deal_sessionостаётся; 5 — заглушки сервисов допустимы (порты с детерминированными локальными реализациями до этапов 6+); 6 — идём по roadmap все этапы.
- Бренд во фронте: Vue-фронт всё ещё показывает «LeadRadar» (LoginView, заголовки). Фронт «не трогаем» — но бренд теперь «Дейл». Менять ли строки бренда во фронте (точечно) или позже?
- Инвайты/оператор: ТЗ требует invite-only + отдельный вход оператора; во фронте такого UI нет. Оставляем dev-seed (admin/admin + дефолтный тенант) до этапа 7? Тогда auth остаётся «как прототип».
- Имена колонок БД: EF генерирует PascalCase (
UpdatedAt), ТЗ/доки местами в SQL-нотации (snake_case). Оставляем PascalCase (конвенция кода) — подтвердить. - Имя куки
deal_session(прототип:leadradar_session) — фронту всё равно; ок? - Сервисы ml/ai/telegram: полный ребилд — это самые крупные этапы. Подтвердить, что локально между этапами допустимы порты с детерминированными заглушками (пока сервисы не написаны), чтобы pipeline/kanban разрабатывать и показывать на синтетических входах.
- Приоритет и темп: продолжать строго по roadmap (Settings → Kanban → Pipeline → Projects → сервисы+Discovery → SaaS-контур) и в каком темпе/объёме на сессию.
Статус на 2026-09-08 (этапы 0–7 завершены): п.2 закрыт — инвайты/оператор реализованы в этапе 7
(API-only: /api/operator/* + /api/join), dev-seed admin/admin остаётся dev-only (Ruling 1);
UI операторской админки и страницы активации — задел этапа 8+. п.1 — бренд во фронте меняется точечно
(как решено); п.3–5 — зафиксированы решениями (PascalCase, deal_session, локальные реализации портов)
и не пересматривались; п.6 — roadmap исполнен: этапы 0–7 пройдены (STATUS.md — 100%, Manual-чек-лист
вынесен отдельно).