2
Статус разработки
stepan edited this page 2026-09-15 22:39:57 +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/STATUS.md). Актуальная версия — здесь, в вики.

Дейл (Deal) — Статус разработки и прогресс

Обновляется в конце каждого захода. Проект в git (ветка main, коммиты на русском) — борд состояния + git-история. Дата последнего обновления: 2026-09-16.

2026-09-16 — переезд на Forgejo. Репозиторий, все ветки, метки, задачи с комментариями, открытые PR и вики перенесены на локальный инстанс http://192.168.31.136:3000/rustam/Deal. CI переведён в .forgejo/workflows/ci.yml (раннер proxmox-runner, метка ubuntu-latest); логика прогонов та же (пуш в main, события МР, ручной запуск, отмена предыдущего прогона того же рефа). Защита main повторена: прямой пуш запрещён, нужен апрув rustam. Доска «Deal Board» воссоздана с колонками Backlog/To Do/In Progress/Review/Done и прежней расстановкой задач. Старый Gitea остаётся только в git-remote gitea-legacy (история).

2026-09-11 — единый контракт источника (generic source). Ядро (домен Cards, Storage-сервис, персистентность, конвейер, wire, фронт) переведено с Telegram-полей карточки на generic-тип SourceItem (SourceRef + SourceContent, вложения — DataRef → общий Storage). Дашборды/канбан/конвейер больше не знают о Telegram; Telegram-специфика — только в тонком адаптере приёма. Tenant-миграции пересозданы с нуля (init). Добавлены extension-point ISourceContentProvider/SourceContentResolver и GET /api/cards/{id}/source. Входящий поток источников — generic (sources.proto/PushSource, SourceIngressGrpcService), PushMessage из telegram.proto удалён. Сухой прогон текста по конвейеру (стоп-правила → ML → ИИ) без записи: POST /api/admin/check-message + UI настроек. Remote-просмотр исходника: TelegramService.ReadSource + TelegramSourceContentProvider + UI «Обновить из источника». Метрика алертинга deal.ai.budget.used.ratio{tenant}; actor/tenant в access-логе; прогресс переклассификации через SSE. Hardening контейнеров (non-root/read-only/limits), шардированная пакетная миграция схем, единый CI (scripts/ci.sh). Ядро: build 5 sln 0/0, Deal.Tests.Unit 1326/1326 PASS, telegram 130/130, ai 52/52, ml 38/38, storage 9/9, фронт build + lint:i18n зелёные. Детали — docs/superpowers/specs/2026-09-11-source-contract-design.md.

2026-09-11 (вечер) — закрыты остатки код-стайла (TD-COMMENTS-IFACE, TD-STYLE-ANALYZERS). Дедупликация <summary>: дублей нет (сканы по тексту и по имени члена — 39 интерфейсов/229 членов). var: гейт csharp_style_var_for_built_in_types = false:warning (ломает сборку), остаток выправлен dotnet format по 5 sln (51 файл), «очевидный/прочий тип» — silent осознанно. Переводы строк: решено LF — .gitattributes (* text=auto eol=lf), .editorconfig → lf, нормализовано 1029 файлов; попутно починены 42 CRLF-.sh (первый прогон удалённого CI падал бы). Понижено 12 новых private XML-доков; добавлены 4 <summary> членам интерфейсов; переведены 3 англоязычных комментария; из индекса убраны 2 __pycache__/*.pyc; STATUS.md — удалён устаревший блок «Осталось (в backlog)» в шапке. Дочистка по контрольному скану краткости: удалены 73 очевидных <param name="ct"> (пересказ сигнатуры) в 17 файлах, ужаты 3 summary (многосентенционные/длинные); контроль: <remarks> 0, inline-<summary> 0, многосентенционных 0, TODO 0. Явные реализации интерфейсов (§11) — остались точечным ревью владельца (43 интерфейса с реализациями, массовая правка не автоматизируется). Сборка 5 sln 0/0; тесты: core 1340/1340, telegram 130/130, ai 52/52, ml 38/38, storage 9/9 — зелёные. Детали — docs/spec/Код-стайл-аудит-2026-09-11.md, §2.

2026-09-11 (ночь) — Gitea-контур. Репозиторий запушен (gitea.khomegeneric.keenetic.pro/rust/Deal), ~4000 спам-пользователей вычищено, регистрация закрыта владельцем. CI перенесён в .gitea/workflows/ci.yml; первый прогон поймал и закрыл кроссплатформенный баг (ModelPool валидировал tenant-id через GetInvalidFileNameChars — на Linux пропускал \); валидация заменена на явный белый список. scripts/ исключён из репозитория (правило владельца: в репе только код) — скрипты сборки/тестов/бэкапов/кодмоды живут только локально; CI-workflow переписан inline. Раннер для CI — на сервере рядом с Gitea (пакет deploy/gitea-runner/).

2026-09-11 (поздний вечер) — явные реализации интерфейсов (вариант A, решение владельца). Правило владельца: классы напрямую не вызываем (исключения — DTO, хелперы, экстеншены), тесты — через интерфейсы, моки — NSubstitute, маркерные классы не используем. Сделано: 161 член в 30 прод-файлах переведён на явные реализации codemod'ом scripts/make_explicit.py; потребители конкретных типов перетипизированы на интерфейсы (8 мест в проде, 17 тест-файлов; самовызовы — ((ISessionClient)this)); 10 маркерных классов заменены маркерными интерфейсами (IKanbanModuleISharedKernel); NSubstitute 6.1.0 подключён к 5 тест-проектам, эталон миграции — FakePasswordHasherTestHashers.New() (фейк удалён); правила зафиксированы в §11 код-стайла. Card/I*Card — implicit (DTO). Оставшиеся 30 фейков — поэтапная миграция (backlog.md, TD-TESTS-NSUBSTITUTE). Build 5 sln 0/0, тесты зелёные.

Все этапы 0–12 выполнены (100%) — см. roadmap

docs/superpowers/plans/2026-09-05-deal-roadmap.md, план этапа 10 docs/superpowers/plans/2026-09-10-deal-stage10-operator-analytics.md и ledgers в .superpowers/sdd/. Live-приёмки на Docker Desktop выполнены: dev-smoke 14/14, SaaS-контур 15/15, prod-контур+mTLS+ observability PASS, backup/restore на копии PASS, runtime-приёмка этапа 10 (оператор-консоль, аналитика, аудит) PASS (см. чек-лист ниже). Осталось Manual: реальные Telegram/LLM-креды (п.5).

Общий прогресс по этапам

Этап Статус Задач Тесты (unit, накопительно) Приёмка
0. Каркас готов 9/9 6 health 200
1. Доступ и мультитенантность готов 6/6 25 auth 1:1
2. Settings (настройки) готов 11/11 175 60/60
3. Kanban (дашборд) готов 15/15 410 94/94
4. Pipeline/«Обработка» готов 13/13 535 74/74
5. Projects («Выбранные») готов 13/13 620 75/75
6. Сервисы telegram/ml/ai + Discovery готов 20/20 830 20/20 + 37/37
7. SaaS-контур (оператор/инвайты/лимиты/аудит/безопасность/prod-деплой/бэкапы/доки) готов 16/16 1123 live SaaS 15/15 (остальное — ⚠ Manual)
8. Code-quality rework (ревью 5 зон) готов 5/5 фаз 1139 build 4 sln 0/0; фронт build OK
9. Единая карточка (слияние Kanban/Projects, /api/cards+/api/containers) готов 11/11 1138 live dev-smoke PASS=14 FAIL=0
10. Оператор-консоль, аналитика, аудит действий, Grafana/Loki-дашборды готов 7/7 1173 live runtime (Docker dev)
11. Локализация UI (вынос строк в ресурсы) готов 7/7 1173 build + lint:i18n зелёные
12. Наблюдаемость/устойчивость/перф + добивка ТЗ готов 4/4 пакетов + добивка 1275 build 4 sln 0/0; telegram 125/125
Итого этапы 012 = 100% 137/137 1275 (core) + 125/52/38 (сервисы)

Финальный прогон этапа 12 (2026-09-10, автономный заход A–D): build Deal.sln 0/0; core 1275/1275 PASS; telegram 125/125; фронт npm run build зелёный (main-чанк 309 kB, словарь в отдельном чанке i18n), npm run lint:i18n зелёный; метрики: /metrics (OTel→Prometheus) во всех 4 процессах, Prometheus targets 5/5 UP; пакеты B (rate-limit/LoginAttemptGuard на Postgres, разлогин suspended, purge) и D (reclassify + токены ML) с зелёными тестами. Всё остановлено (правило «без хвостов»). LEDGER: .superpowers/sdd/deal-stage12-observability-hardening/.

Финальный прогон этапа 10 (2026-09-10): build Deal.sln 0/0; core 1173/1173 PASS; фронт npm run build зелёный; GET /api/operator/analytics/{overview,tokens,activity} и GET /api/operator/audit живьём на dev-Postgres (:5433, миграция AddTokenUsageEvents применена), deal-core healthy; страницы #/operator и #/join отдаются dev-сервером. Детали — ledger .superpowers/sdd/deal-stage10-operator-analytics/progress.md.

Финальный прогон (Task 16, 2026-09-08, docker выключен): build 0 warnings / 0 errors всех четырёх sln (core/telegram/ai/ml); core 1123/1123 PASS, telegram 114/114, ai 50/50, ml 36/36 PASS; docker compose -f deploy/compose.prod.yml config rc=0 (+ профиль observability); sh -n scripts/dev-smoke.sh/backup.sh/restore.sh/mtls-certs.sh rc=0.

Накопительный счётчик core в таблице — по состоянию на конец этапа: этап 8 — 1139, этап 9 — 1138 (часть тестов удалена вместе с доменом Projects), этап 10 — 1173.

Что система умеет СЕЙЧАС (проверяемо)

  • Ядро (этапы 06): вход admin/admin (dev-seed, dev-only), сессии, схемы на тенанта (Postgres :5433); дашборд (колонки/карточки/drag&drop/архив/корзина/FTS-поиск), «Обработка» (очередь→стоп-лист→дедуп→ML/ИИ→карточка), «Выбранные» (стадии/напоминания SSE/файлы Local/MinIO), Настройки (ключи AI enc:, промпты, валюты; Telegram-ключи — глобально у оператора), Каналы/Discovery; полный dev-стек этапа 6 — deploy/compose.dev.yml (Services__*__UseLocal=false, gRPC-режим telegram/ai/ml + ингресс core).
  • SaaS-контур (этап 7): оператор (public.operators/operator_sessions, кука deal_operator_session, bootstrap env DEAL_OPERATOR_*; dev-дефолт operator/operator) и ручки /api/operator/* (auth/tenants/invites/limits/audit/health — с этапа 10 у них есть UI, см. ниже); инвайты (код 16 симв., 72 ч) и активация POST /api/join (пользователь + провижининг тенанта); лимиты ИИ-бюджета (tenant_limits, TokenUsageRecorder, гейт-декораторы → Local-фолбэк, SSE-тосты 80/100%); append-only аудит; rate limiting (auth 10/мин·IP, api 600/мин·тенант, gRPC-ингресс 600/мин·тенант, LoginAttemptGuard 5/15 мин); Origin-проверка мутаций + security-заголовки + ForwardedHeaders за Caddy; mTLS за флагом DEAL_MTLS_* (scripts/mtls-certs.shdeploy/certs/); Serilog JSON во всех 4 процессах (+ access-логи HTTP/gRPC); prod-деплой deploy/compose.prod.yml (caddy 80/443, postgres/minio без host-портов, профиль observability: promtail/loki/grafana, .env.prod.example); бэкапы scripts/backup.sh/restore.sh/deal-backup-lib.sh (pg_dump -Fc + MinIO + tar; retention 14).
  • Оператор-консоль и аналитика (этап 10): hash-роутер фронта (#/ приложение, #/operator консоль, #/join?code=… активация инвайта); разделы консоли (вход, тенанты+suspend/resume/impersonate, инвайты, лимиты, аудит с фильтрами/пагинацией, аналитика, health); impersonation ставит httpOnly-куку deal_session тем же ответом (оператор сразу в тенанте). Сквозной аудит действий (public.audit_log): выходы, invite_joined, действия карточек/комментариев, CRUD контейнеров, настройки, каналы, Telegram. История расхода токенов public.token_usage_events + операторская аналитика (/api/operator/analytics/{overview,tokens,activity}, groupBy=day|tenant|provider|model). Grafana provisioning (datasource Loki + дашборды Deal-Auth/Errors/Rps/Logs) и promtail-лейблы.
  • Что увидеть глазами: полный dev-стек — docker compose -f deploy/compose.dev.yml up -d --build → фронт cd src/frontend && npm run dev → логин admin/admin (dev-seed); либо сквозной smoke одной командой: sh scripts/dev-smoke.sh. Prod-контур — §13.8 техдока (оператор → тенант → инвайт → /api/join). Host-режим (Local-заглушки): postgres/minio + dotnet run --project src/core/Deal.Api --urls http://localhost:5080.
  • Полная карта «что/где» — техдок docs/technical/Техническая-документация-Дейл.md (§5, §7–§11, §13.1–§13.10), api-map docs/api/api-map.md (раздел «Реализовано в Deal»), инструкция пользователя docs/user-guide/Инструкция-пользователя-Дейл.md.

Manual-чек-лист (остаток после live-приёмок)

Выполнено живьём на Docker (автономно от авто-прогонов Task 16, build/test/config/syntax — там же):

  1. SaaS-сквозная приёмка (live, 15/15 PASS)run-live-saas.sh + live-saas-check.sh на поднятом dev-Postgres (:5433, миграции SystemSaaS + SessionsImpersonationMark применены): оператор login → создать тенанта → инвайт → POST /api/join → вход пользователя → settings/cards (на тот момент — boards/демо-карточка) → IDOR-негатив 401 (пользователь к операторским ручкам) → suspend (вход 403) → resume (вход 200) → лимиты (tenant_limits) → аудит-лента. Core погашен, :5080 свободен.
  2. dev-smoke 14/14 PASS — полный gRPC-стек (scripts/dev-smoke.sh): подъём, health, login admin/admin, /api/tg/status idle, POST /api/cards (карточка planned) → trash → обучающий сигнал spam, ML-флашер выгрузил outbox. Стек погашен скриптом (trap).
  3. Prod-контур + mTLS + observability (live) — сертификаты перегенерированы (scripts/mtls-certs.sh -f,) полный набор в deploy/certs; подъём compose.prod.yml + --profile observability с фиктивными env-секретами (DEAL_MTLS_ENABLED=1, endpoint'ы https://): core/telegram/ai/ml healthy под mTLS; исходящее mTLS подтверждено живьём — /api/tg/status (idle) и /api/ml/status (reachable:true) через Caddy; фронт и /api/health через Caddy 200; promtail→loki (логи пишутся), Grafana 200. Исправлен дефект deploy/observability/loki.yml (Loki 3.x: delete_request_store). .env.prod тестовый удалён.
  4. backup/restore (live, на копии)backup.sh: pg (-Fc) + minio (docker-mc) + data (tar docker-томов)
    • retention; restore.sh pg в копию-БД — 43 таблицы/3 схемы идентичны, данные сошлись (users=2, tenants=2, sessions=30); restore.sh minio с реальным объектом (залит→бэкап→удалён→восстановлен); restore.sh data. Исправлены дефекты скриптов, проявившиеся живьём: двойная схема в MC_HOST_deal (deal-backup-lib.sh), пустой бакет → mv (backup.sh), Windows/MSYS docker-пути (host_docker_path).
  5. Реальный Telegram-вход (api_id/api_hash/QR) и LLM-вызовы — нужны живые креды.
  6. Прогон scripts/backup.sh и restore-тест — см. п.4 (полный цикл на dev-хранилищах и копии-БД).
  7. Этап 10 — runtime-приёмка (Docker dev-стек) — миграция AddTokenUsageEvents применена к dev-Postgres (:5433), deal-core пересобран/healthy; операторский вход operator/operator → 200; GET /api/operator/tenants, /audit, /analytics/overview, /analytics/tokens?groupBy=day|provider, /analytics/activity?limit=3 → 200 (реальные лента/агрегаты); фронт npm run build зелёный, dev-сервер отдаёт #/operator и #/join; core-тесты 1173/1173. Детали — ledger этапа 10.

Заделы (этап 13+; подробно — техдок §11 и roadmap)

Единый источник отложенного и техдолга — docs/superpowers/backlog.md. Ниже — краткая выжимка.

  • Этап 11 — Локализация интерфейса (i18n)выполнен (2026-09-10, урезанный объём): все пользовательские строки фронта в ресурсах (src/frontend/src/i18n/, 1039 ключей в 13 областях), линтер npm run lint:i18n. Переключатель языка и второй язык — в бэклоге: делаем, когда появится потребность (ядро i18n/registerLocale к этому готово).
  • Этап 12 — Наблюдаемость/устойчивость/перфвыполнен (2026-09-10, автономно, пакеты A–D): метрики Prometheus+Grafana (/metrics :9464 во всех процессах); распределённый rate-limit и LoginAttemptGuard на Postgres; мгновенный разлогин suspended-сессий; авто-purge audit_log/tenant_limits; разбиение бандла фронта + прогрессивный рендер колонок; LRU-кэши WTelegram; пакетная миграция схем тенантов; реальный reclassify с Local-фолбэком. LEDGER: .superpowers/sdd/deal-stage12-observability-hardening/.
  • Остатки этапа 12 (закрыто 2026-09-10): доки под этап 12 (real-reclassify, maintenance-migrate, без демо), Prometheus alert rules (deploy/observability/prometheus-rules.yml + провижининг), устранена гонка FreeTcpPort() в тест-харнессе (единый TestPort), SSE cards_reclassified (бэк+фронт), нагрузочные скрипты scripts/loadtest/, скан уязвимостей — чисто (core: 0 уязвимых пакетов; frontend npm audit: 0).
  • Прочее (требует владельца/кредов): биллинг/провайдер планов и саморегистрация; мультиаккаунтность Telegram; k8s/Cloudflare; Kafka; экспорт/импорт ML; переключатель языка/второй язык (в бэклоге — по потребности); реальный Telegram-вход и живые LLM-вызовы; legacy-прототип docker-compose.yml перенесён в archive/leadradar-legacy/ (2026-09-10).
  • Добивка по ТЗ (2026-09-10, автономно) — закрыты найденные аудитом частично/незакрытые пункты: ML-проверка на канале/сообщении (/api/ml/candidates+/apply — реальные, не заглушки); глобальные исключения до ML/ИИ (§5.14); новые группы фильтров колонки levels/locations/types/prices (§6.3); «открыть исходник» как быстрое действие на карточке (§6.6); глубины очередей/сессии в /api/operator/health (§10.2); детектор подозрительной активности /api/operator/analytics/suspicious (§10.5); раздел настроек и поддержка тем «Внешний вид» — тёмная (дефолт) / светлая / системная (§8.12). Отчёт аудита: docs/superpowers/reviews/2026-09-10-tz-compliance-audit.md. Core-тесты 1275/1275; фронт build+lint:i18n зелёные.
  • Telegram-ключи — вариант A (2026-09-10, по решению владельца): api_id/api_hash задаёт оператор глобально (таблица public.global_settings, ручки GET/PUT /api/operator/settings/telegram-keys, hash шифруется; раздел «Telegram» в оператор-консоли). У тенанта ключи убраны — только подключение аккаунта; без ключей подключение недоступно (/api/tg/status → keysSet:false). Миграция GlobalSettings применена; PUT поддерживает частичное обновление (можно сменить одно поле). Core-тесты 1275/1275.

Code-quality rework (2026-09-08, после ревью 5 зон ~1100 файлов)

Проведено многоосевое ревью (безопасность/корректность/архитектура/перф) бэкенда и фронта; findings — docs/superpowers/reviews/2026-09-08-code-quality-review.md. Все исправления закрыты и проверены: core 1135/1135, telegram 118/118, ai 52/52, ml 38/38, фронт build OK, 4 sln 0/0. Главное:

  • Безопасность: SSRF-гейт (baseUrl каталоговых провайдеров фиксирован + private-IP-блок в проверке), fail-closed Production (rate limit/CORS/conn-string обязательны), код инвайта в аудите — SHA-256, пароль ≥8, маска ключа не перезаписывает ключ и короткие секреты скрыты, TenantId = 32-hex, mTLS fail-closed, gRPC-лимиты входных данных, join проверяет целевого тенанта, атомарный инкремент токенов (Npgsql).
  • Корректность: атомарные append комментариев/ссылок/файлов (1 SQL), уникальный objectKey, атомарный дедуп-pump, запрет move из trash/archive/taken, логирование «немых» catch, очистка сессий вне hot-path; фронт: смена пароля с текущим паролем, boot не падает от одного 500, автосейв не затирает промпты, гонки поиска закрыты seq-токенами.
  • Архитектура: Deal.Grpc.Hosting (общая обвязка 3 сервисов), TenantSettingsSnapshot (9 копий чтения настроек → одна), декомпозиция 7 крупных файлов на partial (<350 строк), фронт store.js → слайсы store/, вынесены компоненты Settings/Discovery; мёртвый код удалён.
  • Реестры констант (C35, 2026-09-09): общие Deal.Contracts.Integrations.MlLearningLabels (spam/t:hire/t:order) и SourceDefaults (DefaultHue) вместо дублей в 5 модулях; единый предикат «активные правила» (Kanban ColumnRules.HasActiveRules); реестр id-стадий ProjectStages (с этапа 9 — CardsDefaultContainers); общий CardsService.JustNowLabel; TTL-эвикция в DiscoverySearchErrorCounter (+4 теста, core 1139).
  • Заделы (не рисковали без e2e/не успели): вынос оставшихся вкладок SettingsView, Optional-пункты (пагинация колонок, виртуализация, LRU-кэши WTelegram и др.). Подробности — в отчёте ревью и .superpowers/sdd/deal-stage8-quality-rework/.

Процесс (обязательства, чтобы не жрать память/хосты)

  • Acceptance-серверы — только через враппер с гарантированным kill (taskkill //T //F по PID-файлу) + проверка освобождения порта; в конце каждой приёмки — шаг очистки.
  • Контейнеры — по требованию (docker compose ... up|down); между заходами ничего не держать; scripts/cleanup-dev.sh (kill висящих Deal.*/тест-хостов, dotnet build-server shutdown, остановка deal-контейнеров) — в конце захода.
  • Хвостов не оставлять (правило владельца, 2026-09-10): по завершении работы все сервисы и процессы должны быть остановлены — включая Docker-контейнеры и dev-серверы (frontend/Vite, dotnet) — если владелец явно не попросил оставить их запущенными. Проверка в конце: docker ps без deal-*, свободные порты (5173/5080/5082/5101/5102/5103/5433/9000/9001/9464), dotnet build-server shutdown.
  • Разовые решения — одним списком в начале (правило владельца, 2026-09-10): все вопросы, требующие выбора владельца, собираются и задаются сразу, до начала работы, а не по ходу/в конце. Не спрашивать о том, что уже определено ТЗ/принятыми решениями — это делать без вопросов; вопрос — только при реальном противоречии в требованиях. При неоднозначности без противоречий — выбирать безопасный обратимый дефолт и делать (напр. перенос, а не удаление).
  • Легаси-прототип LeadRadar перенесён из корня в archive/leadradar-legacy/ (2026-09-10; обратимо, на сборку/запуск не влияет).