1
План roadmap
stepan edited this page 2026-09-13 00:17:00 +03:00
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.

Перенесено из репозитория (docs/superpowers/plans/2026-09-05-deal-roadmap.md). Актуальная версия — здесь, в вики.

Дейл (Deal) — Roadmap этапов (все этапы 0–7 выполнены; 2026-09-08)

Исторический документ (roadmap этапов 07, 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/TenantContext AsyncLocal/ConnectionStringProvider search_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 c MigrationsHistoryTable("__TenantMigrationsHistory", schema)), TenantBootstrapService (seed: тенант id 000…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: в БД, ключ env DEAL_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. Задачи 115 приняты: 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 + SSE reminder_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 с python mlservice/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-вызовы; живой smoke scripts/dev-smoke.sh — после поднятия Docker. Ограничения этапа 6 (переходят в этап 7): mTLS-сертификаты и prod-compose; лимиты/бюджеты токенов (учёт aiTokenUsage уже есть); оператор/админка/аудит-поток; rate limiting gRPC; экспорт/импорт ML-моделей; ротация/бэкап ключей сессий; reclassify на реальном ИИ (контракт-заглушка остаётся).

  • Этап 7 — SaaS-контур (Tasks 116, 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 (этапы 07 = 100%). Финальный прогон: core 1123/1123 PASS, telegram 114/114, ai 50/50, ml 36/36 PASS, build 0/0 всех четырёх sln, compose.prod.yml config rc=0, sh -n скриптов rc=0. Ledger: .superpowers/sdd/deal-stage7-saas/. Manual (нужен docker/живые креды): применение system-миграции + сквозная SaaS-curl-приёмка, подъём compose.prod и dev-smoke scripts/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 все этапы.

  1. Бренд во фронте: Vue-фронт всё ещё показывает «LeadRadar» (LoginView, заголовки). Фронт «не трогаем» — но бренд теперь «Дейл». Менять ли строки бренда во фронте (точечно) или позже?
  2. Инвайты/оператор: ТЗ требует invite-only + отдельный вход оператора; во фронте такого UI нет. Оставляем dev-seed (admin/admin + дефолтный тенант) до этапа 7? Тогда auth остаётся «как прототип».
  3. Имена колонок БД: EF генерирует PascalCase (UpdatedAt), ТЗ/доки местами в SQL-нотации (snake_case). Оставляем PascalCase (конвенция кода) — подтвердить.
  4. Имя куки deal_session (прототип: leadradar_session) — фронту всё равно; ок?
  5. Сервисы ml/ai/telegram: полный ребилд — это самые крупные этапы. Подтвердить, что локально между этапами допустимы порты с детерминированными заглушками (пока сервисы не написаны), чтобы pipeline/kanban разрабатывать и показывать на синтетических входах.
  6. Приоритет и темп: продолжать строго по 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-чек-лист вынесен отдельно).