Files
Deal/docs/superpowers/backlog.md
T
Rustam Khalimov 195faf1b1f
ci / build-test (pull_request) Successful in 2m56s
ci / build-test (push) Successful in 2m52s
Восстановить docs/ как зеркало для агентов (ревью МР #11)
Ревью rust: перенос в вики не должен удалять из репозитория то, что нужно
агенту для работы (бэклог, статус, планы, код-стайл, спеки). Дублирование
вики и репы разрешено и обязательно: вики — актуальные версии для людей,
docs/ — зеркало для контекста агентов. README разведён по ролям.
2026-09-12 23:54:28 +03:00

96 lines
18 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.
# Бэклог (техдолг и отложенные задачи) — «Дейл»
> Назначение: единый источник отложенного/запланированного. Роудмап черпается отсюда.
> Статусы: **BACKLOG** (сделаем при потребности), **DEFERRED** (отложено осознанно, вне текущих рамок),
> **MANUAL** (нужны внешние условия: креды, хост, прод), **TECHDEBT** (качество/архитектура).
> Приоритет: P1 (важно), P2 (полезно), P3 (когда-нибудь).
> Обновлять при каждом заходе; выполненные пункты переносить в `docs/superpowers/STATUS.md` и вычёркивать здесь.
## 1. Продуктовые фичи (по потребности)
| ID | Пункт | Источник | Приоритет | Статус |
|---|---|---|---|---|
| BL-I18N | Переключатель языка в UI + второй язык (en) + locale-aware форматирование (`Intl`), плюрализация. Основа (вынос строк в ресурсы, `registerLocale`) готова | ТЗ §11, этап 11 | P3 | BACKLOG |
| BL-TG-MULTI | Мультиаккаунтность Telegram (сейчас 1 аккаунт на тенант) | ТЗ §12 | P2 | DEFERRED |
| BL-ML-EXP | Экспорт/импорт ML-моделей (перенос «мозгов» между инстансами) | обсуждение этапа 12 | P3 | DEFERRED (решено не делать; вернуться при SaaS-масштабе) |
| BL-RECLASS-SSE | **Сделано (2026-09-11):** пакетная переклассификация отдаёт промежуточный прогресс через SSE `cards_reclassified` (`{progress:true,done,total,moved,kept,trashed,skipped}`) и финальное событие (`{progress:false,reclassified,moved}`); `CardReclassifier.ReclassifyInboxAsync` принимает `IProgress<ReclassifyProgressDto>`; в UI — индикатор `done/total` в шапке «Неразобранного» | этап 12, D | P3 | DONE |
| TD-CARD-MERGE | Полное слияние внутренних DTO карточки в единый `CardDto`. **Решение (2026-09-11): DEFERRED.** Наружный контракт единый; внутренние DTO (read/write/DB/patch) намеренно разделены по слоям, слияние — риск без пользы | этап 9/11 | P3 | DEFERRED |
| TD-PROTO-COMMENTS | **Сделано (2026-09-11):** из комментариев убраны ссылки на процесс/прототип (`Task/Ruling/этап/python L…/main.py/прототип/LEADRADAR_*`), удалены блоки `<remarks>`, `<summary>` сжаты до короткой фразы; `//`-комментарии со ссылками удалены, в `.proto` — тоже. Строк комментариев 27 210 → ~19 100 | запрос владельца 2026-09-11 | P2 | DONE |
| TD-COMMENTS-IFACE | Привести код к правилам код-стайла (`docs/spec/Код-стайл-Дейл.md`). **Сделано (2026-09-11):** (1) `<summary>` только блочно — 5286 шт.; (2) приватные XML-доки понижены — 2028+12; (3) дедупликация `<summary>``<inheritdoc/>` — дублей нет (сканы); (4) **явные реализации интерфейсов — сделано (2026-09-11, вечер, вариант A)**: 161 член в 30 прод-файлах конвертирован codemod'ом `scripts/make_explicit.py`, потребители перетипизированы на интерфейсы (8 мест в проде, 17 тест-файлов), Card/ICard-семейство оставлено implicit как DTO; попутно маркерные классы заменены маркерными интерфейсами. Детали — `docs/spec/Код-стайл-аудит-2026-09-11.md` | запрос владельца 2026-09-11 | P2 | DONE |
| TD-TESTS-NSUBSTITUTE | Миграция тестовых фейков на NSubstitute (решение владельца 2026-09-11: моки — через NSubstitute, новых фейк-классов не заводить). **Сделано (2026-09-11):** NSubstitute 6.1.0 подключён к 5 тест-проектам; эталон миграции — `FakePasswordHasher` → хелпер `TestHashers.New()` (NSubstitute, детерминированная семантика сохранена), фейк удалён. **Осталось (по размеру):** FakeDiscoveryPacer (1 файл), FakeRatesListener (2), FakeTenantProvisioner (5), FakeSecretCipher (8), FakeAiTools (4), FakeRatesSource (1), FakeGlobalSettingsStore (4), FakeTenantRegistry/FakeTenantRepository (3+7), FakeAiClassifier (5), FakeSettingsStore (42), FakeRateLimitCounterStore (5), FakeAuditLogStore (13), FakeTenantStore (10), FakeMlLearningStore (5), FakeMlClient (17), FakeOperatorAuthStore (14), FakeInviteStore (7), FakeFileStorage (9), FakeTokenUsageEventStore (10), FakeAuthStore (15), Recording*/Harness* (gRPC-харнессы — оставить как хелперы), крупные stateful: FakeTelegramGateway (5), FakeDiscoveryGateway (2), FakeTelegramStore (7), FakeTenantLimitStore (15), FakePipelineStore (12), FakeDiscoveryStore (7), FakeKanjStore (21). Для каждого: заменить подставку на `Substitute.For<>()` + `Returns`, семантику состояния воспроизвести в конфигурации, тесты перетипизировать на интерфейс | решение владельца 2026-09-11 | P2 | BACKLOG |
| TD-STYLE-ANALYZERS | Остаток мягких правил код-стайла. **Закрыто (2026-09-11):** (1) `var` — включён ломающий сборку гейт только для встроенных типов (`csharp_style_var_for_built_in_types = false:warning`), остаток выправлен `dotnet format style --diagnostics IDE0008` по 5 sln; режимы «очевидный/прочий тип» — silent осознанно (~1600 субъективных замен); (2) дедупликация `<summary>` — дублей нет (см. TD-COMMENTS-IFACE); (3) переводы строк — **решено: LF** (`.gitattributes` `* text=auto eol=lf`, `.editorconfig` → lf, 1029 файлов нормализовано, `git add --renormalize`; попутно починены 42 CRLF-.sh — до этого первый прогон удалённого CI падал бы). `this.` и именование приватных полей уже закрыты в `.editorconfig` | аудит 2026-09-11 | P3 | DONE |
## 2. Инфраструктура и эксплуатация
| ID | Пункт | Источник | Приоритет | Статус |
|---|---|---|---|---|
| BL-K8S | Kubernetes-манифесты (сейчас docker-compose; k8s — при масштабировании) | ТЗ §11/§12, R6 | P3 | DEFERRED |
| BL-KAFKA | Kafka как шина данных между сервисами (сейчас gRPC + БД-outbox) | ТЗ §12, обсуждение | P3 | DEFERRED |
| BL-CF | Cloudflare / внешний периметр (сейчас Caddy, mTLS; конфиг вне кода) | ТЗ §11, техдок §10 | P2 | MANUAL |
| BL-CI | **Сделано (2026-09-11):** `scripts/ci.sh` — сборка всех 5 решений, тесты всех сервисов, скан уязвимых NuGet-зависимостей (`dotnet list package --vulnerable --include-transitive`), сборка+линтер фронта; `build.sh`/`test.sh` расширены на все решения/сервисы; `.github/workflows/ci.yml`. Первый прогон в удалённом CI — при публикации репозитория | техдок §8 | P2 | DONE (remote — MANUAL) |
| BL-IMG-HARDEN | **Сделано (2026-09-11):** non-root USER (deal, UID 10001, HOME=/tmp) во всех прикладных образах; в compose — read_only root FS + tmpfs /tmp, no-new-privileges, cap_drop ALL, mem_limit/cpus; логи stateless-сервисов в /tmp/logs. Проверено `compose config` (dev/prod/observability); живой прогон — MANUAL | техдок §10 | P2 | DONE (live — MANUAL) |
| BL-BACKUP-CRON | Автоматизация бэкапов (cron/systemd-примеры есть, реальный прогон — MANUAL) | техдок §9 | P2 | MANUAL |
## 3. SaaS / мультитенантность
| ID | Пункт | Источник | Приоритет | Статус |
|---|---|---|---|---|
| BL-BILLING | Биллинг и тарифные планы, провайдер платежей | ТЗ §12 | P3 | DEFERRED |
| BL-SIGNUP | Саморегистрация тенантов (сейчас инвайты/оператор) | ТЗ §12 | P3 | DEFERRED |
| BL-SCALE-1000 | Механизм миграций/провижининга на 1000+ схем. **Сделано (2026-09-11):** пакетная миграция шардирована — `ITenantRepository.ListPageAsync` + обход страницами в `TenantSchemaMigrationService` (параллелизм внутри страницы, `DefaultPageSize=200`, границы 1..32 / 1..5000), сбои изолированы. Осталось при росте: вынести параллелизм/размер в конфиг и кэш прогресса (при необходимости) | roadmap этап 0, этап 12 | P2 | DONE |
## 4. Безопасность и наблюдаемость (доработки)
| ID | Пункт | Источник | Приоритет | Статус |
|---|---|---|---|---|
| BL-ALERT-BUDGET | **Сделано (2026-09-11):** метрика `deal.ai.budget.used.ratio{tenant}` (доля израсходованного ИИ-бюджета периода, 0..1) в `DealMetrics` + сбор в `RuntimeDepthsCollector`/`DealMetricsCollector`; на её основе оператор настраивает алерт в Prometheus/Grafana | этап 12, A | P2 | DONE |
| BL-LOG-ACTOR | **Сделано (2026-09-11):** access-лог HTTP core (`HttpAccessLogMiddleware`) включает `actor` (login пользователя тенанта либо оператора) и `tenant` (id тенанта) — их берут из `HttpContext.Items` (Session/OperatorSession middleware) | этап 12, T6 | P3 | DONE |
| BL-GRACEFUL | Дополнительные проверки устойчивости/ретраев (по результатам нагрузочного прогона) | этап 12, C | P2 | BACKLOG |
| BL-SUSPICIOUS | **Сделано (2026-09-11):** детектор `SuspiciousActivityService` расширен правилом `distinct_logins_per_ip` (перебор разных логинов с одного IP, порог `DistinctLoginsPerIpThreshold`); плюс real-time `SuspiciousActivityReporter` — метрика `deal.security.suspicious{kind}` + warn-лог на 429 rate limiter (`rate_limit`) и блокировке входа (`login_blocked`) | ТЗ §10.5, этап 12 | P3 | DONE |
## 5. Технический долг (качество/архитектура)
| ID | Пункт | Источник | Приоритет | Статус |
|---|---|---|---|---|
| TD-SETTINGS-UI | Вынос вкладок `SettingsView` в компоненты. **Сделано (2026-09-11):** `SettingsView.vue` — только набор вкладок/QR-опрос, все 10 вкладок — отдельные компоненты (`components/settings/*`) | ревью 2026-09-08 | P3 | DONE |
| TD-VIRT | Полная виртуализация длинных колонок. **Решение (2026-09-11): DEFERRED** — прогрессивный рендер «Показать ещё» покрывает текущие объёмы; виртуализация — при росте списков | ревью, этап 12 | P3 | DEFERRED |
| TD-SSE-DEAD | **Сделано (2026-09-11):** мёртвые SSE-ветки фронта `boards_changed`/`pipeline_stats` удалены из `store/lifecycle.js` (core их не публикует) | этап 12, E | P3 | DONE |
| TD-DBL-CLICK | **Сделано (2026-09-11):** перезагрузка доски при batch-переклассификации коалесцируется `scheduleBoardReload()` (ответ + SSE → один запрос) | этап 12, E | P3 | DONE |
| TD-TEST-HARNESS | Историческая гонка `FreeTcpPort` — устранена; следить за новыми хост-хелперами | этап 12, E | P3 | TECHDEBT |
| TD-OLD-DOCS | Исторические доки несут старые термины под пометками. **Проверено (2026-09-11):** `docs/superpowers/plans/*` и старые `docs/architecture/2026-09-0*` имеют шапку «Исторический документ»; переписывать не нужно | docs sweep | P3 | DONE |
| TD-SOURCE-PROVIDER | Провайдеры содержимого источников. **Сделано (2026-09-11):** `TelegramSourceContentProvider` + `ReadSource` RPC + `GET /api/cards/{id}/source` + UI «Обновить из источника». Осталось: провайдеры прочих источников по мере появления | generic source 2026-09-11 | P2 | TECHDEBT |
| TD-STORE-ATTACH | Выгрузка вложений источника в Storage-сервис адаптером. **Решение (2026-09-11): медиа-посты Telegram пропускаем** — извлечение/выгрузка не делаются; вложений у прочих источников пока нет — **DEFERRED** (контракт `DataRef` готов, включается при появлении такого источника) | generic source 2026-09-11 | P3 | DEFERRED |
| TD-TG-CORE-SPLIT | Перенос оставшейся Telegram-специфики ядра в telegram-сервис. **Закрыто (2026-09-11): не требуется.** Задача «дашборды/карточки не знают о Telegram» решена generic-контрактом источника; оставшиеся `TelegramStore`/`Dialogs`/`TgMessages`/Discovery — это состояние тенанта (ядро — владелец данных, telegram-service — stateless-шлюз), перенос отдал бы шлюзу доступ к схеме тенанта | generic source 2026-09-11 | — | CLOSED |
| TD-SOURCE-CONTACTS | Квалификатор контактов знает форматы профилей (t.me/`@handle`). **Решение (2026-09-11): DEFERRED** — форматы стабильны, расширяемость под источник добавляется при конкретной потребности | generic source 2026-09-11 | P3 | DEFERRED |
| TD-APIMAP-COUNT | Ручной подсчёт числа ручек в `api-map`. **Сделано (2026-09-11):** сверил счётчики §3.1–§3.8 с фактическими строками (рассинхрон §3.5 — 14→15 из-за `GET /cards/{id}/source`); в §3 добавлено правило обновлять счётчики | docs sweep | P3 | DONE |
## 6. Manual-проверки (нужны внешние условия)
| ID | Пункт | Источник | Приоритет | Статус |
|---|---|---|---|---|
| MN-E2E-TG | Реальный Telegram-вход (QR) + приём сообщений, backfill, «Перечитать каналы» | ТЗ §4, STATUS | P1 | MANUAL (креды/аккаунт) |
| MN-E2E-LLM | Живые LLM-вызовы (классификация/фильтр/reclassify/расход токенов) | ТЗ §89 | P1 | MANUAL (LLM-ключ) |
| MN-PROD | Прод-развёртывание (хост/домен, Caddy+mTLS, observability-профиль) | техдок §13.8 | P2 | MANUAL (данные хоста) |
| MN-GRAFANA | Живая проверка Grafana-дашбордов метрик/алертов и логов | этап 12, A/T6 | P2 | MANUAL |
| MN-LOADTEST | Живой нагрузочный прогон (`scripts/loadtest/`) и baseline | этап 12, C | P2 | MANUAL |
| MN-BACKUP | Живой прогон `backup.sh`/restore на реальных данных | техдок §9 | P2 | MANUAL |
| MN-THEME | Визуальная приёмка светлой темы в браузере | этап 12, «Внешний вид» | P3 | MANUAL |
## 7. Отложено/решено «не делать» (для истории)
| ID | Пункт | Решение |
|---|---|---|
| DEC-DEMO | Демо-эндпоинты (`DEAL_DEMO`, `simulate-lead`) | Удалены (этап 9/12) |
| DEC-LEGACY | Легаси-прототип LeadRadar (`backend/`, `mlservice/`, корневой compose) | Перенесён в `archive/leadradar-legacy/` (2026-09-10); 2026-09-11 убран и из репозитория — лежит только локально |
| DEC-ML-EXP | Экспорт/импорт ML | Отложено владельцем (перенесено в `BL-ML-EXP`) |
---
## Как пользоваться
- Для нового захода: выбрать пункты по приоритету/теме, оформить SDD-план в `docs/superpowers/plans/`
и ledger `.superpowers/sdd/<этап>/`, после приёмки — перенести факт в `docs/superpowers/STATUS.md`,
а пункт здесь пометить выполненным/удалить.
- Открытые пункты (BACKLOG/MANUAL) зеркалятся задачами в Gitea (`rust/Deal`, метки P1/P2/P3/manual/techdebt);
при закрытии пункта закрывать задачу и наоборот.
- Пункты `MANUAL` не блокируют разработку; выполняются, когда владелец даёт креды/хост.