Ревью rust: перенос в вики не должен удалять из репозитория то, что нужно агенту для работы (бэклог, статус, планы, код-стайл, спеки). Дублирование вики и репы разрешено и обязательно: вики — актуальные версии для людей, docs/ — зеркало для контекста агентов. README разведён по ролям.
96 lines
18 KiB
Markdown
96 lines
18 KiB
Markdown
# Бэклог (техдолг и отложенные задачи) — «Дейл»
|
||
|
||
> Назначение: единый источник отложенного/запланированного. Роудмап черпается отсюда.
|
||
> Статусы: **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/расход токенов) | ТЗ §8–9 | 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` не блокируют разработку; выполняются, когда владелец даёт креды/хост.
|