Files
Deal/docs/superpowers/plans/2026-09-05-deal-roadmap.md
T
Rustam Khalimov 9e07568ddd Инициализировать репозиторий «Дейл»
Первый коммит: модульный монолит ядра (.NET 10) и gRPC-сервисы
ai/ml/telegram, фронтенд Vue 3/Vite/Tailwind, документация (ТЗ,
инструкция пользователя, техдокументация, код-стайл), бэклог,
скрипты развёртывания и архив прототипа LeadRadar.
2026-09-11 02:50:17 +03:00

174 lines
20 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) — 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 (этапы 07 завершены):** п.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-чек-лист
вынесен отдельно).