DealDocumentScreening/docs/TICKETS.md

16 KiB
Raw Permalink Blame History

Тикеты реализации «Контракт-чек» (production refactor)

Актуальная архитектура: ARCHITECTURE.md (supersedes IMPLEMENTATION_PLAN.md для этапов 1+). Состояние кода на момент синхронизации: реализованы api/ (вкл. B2B-роуты, web-auth, passkeys, magic links), core/, worker_extract/, worker_prescreen/, worker_analyze/, worker_notify/, bot/; 6 Dockerfile-ов в srv/; docker-compose.yml разводит профили services и edge; миграции 0001_initial0010_passkeys_magic_links; unit- и интеграционные тесты зелёные. DoD: ruff check src tests, ruff format --check src tests, uv run ty check src, pytest зелёные; .env.example актуален.

Статусы: todo / in_progress / done / blocked.


Аудит реализации (текущее состояние)

Проверено: код собирается (pyproject.toml + uv.lock), миграции накатываются, api/ стартует, unit-тесты проходят (≈80 тестов зелёные), интеграционные тесты проходят на поднятой инфраструктуре.

Компонент Статус Доказательство / пробел
Stage 0 prototype removed Удалён: standalone CLI больше не нужен; tests/unit/test_checklist_report.py, test_chunker.py, test_extractor.py зелёные.
core/ — общий домен done db/ (models, session, enums, repositories), mq/, s3/, llm/, analysis/, extraction/, notifications/, security/, credits.py, tokens.py, api_keys.py, rate_limit.py, redis_client.py, config.py, logging.py, metrics.py, telemetry.py, sentry.py, passkeys.py.
Миграции / БД done 0001_initial.py (6 таблиц) … 0010_passkeys_magic_links.py (passkeys, magic links, user name).
api/ — FastAPI ядро done POST /api/v1/documents, GET /api/v1/reports/{id}, GET /api/v1/me, /healthz, /readyz, /metrics; user JWT auth (/api/v1/auth/telegram/*, /api/v1/auth/{register,login,...}, passkeys, magic links); B2B /api/v1/analyze; /admin/*; reserve-on-enqueue (services.py).
worker_extract/ done consumer.py/handler.py/extract_document.py/__main__.py: consume DocumentUploaded → MinIO dl → extract/OCR → .txt upload → publish PrescreenRequested (или DocumentExtracted, если прескрин выключен); failure-class + refund.
worker_prescreen/ done consumer.py/handler.py/__main__.py + extractor*.py/router.py/config.py: consume PrescreenRequested → гибридная экстракция метаданных → роутинг deep_analysis/manual_review/auto_approve; публикация AnalyzeRequested или терминальный статус/лёгкий отчёт.
worker_analyze/ done consumer.py/handler.py/__main__.py: consume DocumentExtracted → LLM → Report → status=done; refund-on-DLQ по политике.
worker_notify/ done consumer.py/handler.py/__main__.py: consume NotificationMessage → SMTP (password reset, magic link) или dev-лог при пустом SMTP_HOST.
bot/ — Telegram adapter done client.py/config.py/handlers.py/__main__.py: /start, upload→POST /documents, poll→deliver; граница импортов проверяется tests/unit/test_bot_boundary.py.
Dockerfile-ы done srv/{api,worker-extract,worker-prescreen,worker-analyze,worker-notify,bot}/Dockerfile — все 6 (deps-группы PEP 735 заточены на сервис).
Docker Compose done Инфра (default) + профиль services (api + worker-ы) + профиль bot (Telegram-адаптер, можно на отдельном хосте) + профиль edge (nginx+certbot) с depends_on: service_healthy. Профили obs/observer — позже.
Observability in_progress Prometheus-метрики (/metrics), Sentry, OpenTelemetry SDK — в коде. Полный стек Prom/Grafana/Tempo/OTel-collector — позже.
Stage 3 — B2B API done api/routes/b2b.py, core/api_keys.py, core/rate_limit.py, core/redis_client.py, миграция 0002_api_keys.py, tests/integration/test_b2b_api.py, tests/unit/test_rate_limit.py; X-API-Key auth + token-bucket rate-limit.

Этап 0 — Прототип (go/no-go)

T-E0-001 — Аккаунт Ollama Cloud + каркас прототипа

Статус: done · Оценка: S

.env.example содержит OLLAMA_HOST/OLLAMA_API_KEY/OLLAMA_MODEL=qwen2.5:14b/OLLAMA_FALLBACK_MODEL=qwen2.5:7b. python -m contract_check --help работает. Теги без -instruct.

T-E0-002 — Экстрактор текста (PDF/DOCX)

Статус: done · Оценка: S

src/contract_check/core/analysis/extractor.py; покрыт tests/unit/test_extractor.py.

T-E0-003 — Чек-лист анализа (v1)

Статус: done · Оценка: S

src/contract_check/core/analysis/checklist.py — 10 пунктов с id/title/description.

T-E0-004 — Ollama Cloud-клиент + repair-loop

Статус: done · Оценка: M

src/contract_check/core/llm/ollama_cloud.py; мок-тесты 200/429-fallback/битый-JSON в tests/unit/test_llm_ollama_cloud.py.

T-E0-005 — Промпт + JSON-отчёт (с чанками)

Статус: done · Оценка: M

core/analysis/analyzer.py, chunker.py, report_schema.py; disclaimer в markdown.

T-E0-006 — Замеры метрик и economics go/no-go

Статус: todo · Оценка: M

Требует живых прогонов 35 договоров через Ollama Cloud + docs/stage0-results.md.


Этап 1 — Production refactor (api + core + workers + bot)

Архитектура: hexagonal, RabbitMQ pipeline (extract.qanalyze.q), MinIO, Postgres, Redis. Профили Docker Compose: default = инфра; services = api + workers; bot = Telegram-адаптер.

T-E1-001 — Ядро contract_check.core

Статус: done · Оценка: L

Пакет src/contract_check/core/ содержит db/, mq/, s3/, llm/, analysis/, credits.py, tokens.py, config.py, logging.py, metrics.py, telemetry.py, sentry.py.

T-E1-002 — Миграции БД (6 таблиц)

Статус: done · Оценка: M

migrations/versions/0001_initial.py: users, documents, reports, jobs, service_tokens, invoices (stub).

T-E1-003 — FastAPI ядро: документы, кредиты, enqueue, отчёты

Статус: done · Оценка: L

src/contract_check/api/: POST /api/v1/documents, GET /api/v1/reports/{id}, GET /api/v1/me, /healthz, /metrics. Reserve-on-enqueue (core/credits.py) и user JWT auth (core/auth.py, api/routes/auth/).

T-E1-004 — Worker-extract (CPU: pymupdf + tesseract)

Статус: done · Оценка: M · Зависимости: T-E1-001, T-E1-002

src/contract_check/worker_extract/ (consumer.py/handler.py/extract_document.py/__main__.py): consume DocumentUploaded из extract.q → скачать blob из MinIO → extractor + ocr.ocr_pdf() → загрузить .txt → publish PrescreenRequested в prescreen.q (или DocumentExtracted в analyze.q, если прескрин выключен). Failure-classification + refund-on-DLQ. Образ srv/worker-extract/Dockerfile.

T-E1-005 — Worker-analyze (I/O: LLM provider)

Статус: done · Оценка: M · Зависимости: T-E1-001, T-E1-002, T-E1-004

src/contract_check/worker_analyze/ (consumer.py/handler.py/__main__.py): consume DocumentExtracted из analyze.q → скачать .txt → chunk → LLM (через core/llm port) → validate/repair → сохранить Report, status=done; refund при terminal failure (core/credits.py). Образ srv/worker-analyze/Dockerfile.

T-E1-006 — Telegram-бот (aiogram 3) — HTTP-адаптер

Статус: done · Оценка: M · Зависимости: T-E1-003

src/contract_check/bot/ (client.py/config.py/handlers.py/__main__.py): /start, приём PDF/DOCX → POST /api/v1/documents, poll GET /api/v1/reports/{id} → отправка отчёта (разбивка/файл >4096 симв.), реакция на 402/400/202. Образ srv/bot/Dockerfile. Не импортирует core.db/core.s3/core.llm/core.mq/core.credits (проверяется tests/unit/test_bot_boundary.py).

T-E1-007 — Docker Compose: сервисы и профили

Статус: done · Оценка: M · Зависимости: T-E1-004, T-E1-005, T-E1-006

docker-compose.yml: default-профиль = инфра (postgres, redis, rabbitmq, minio, minio-init); профиль services = api, worker-extract, worker-prescreen, worker-analyze, worker-notify с depends_on: service_healthy; профиль bot = bot (Telegram-адаптер), можно поднять на этом же или на отдельном хосте; профиль edge = nginx+certbot. Все 7 Dockerfile-ов в srv/. Профили obs/observer добавляют observability-стек.

T-E1-008 — Оплата (ЮKassa) и пополнение кредитов

Статус: done · Оценка: M · Зависимости: T-E1-003, T-E1-006

Реализовано треком .scratch/user-profile-billing/ (тикеты 001019): порт PaymentProvider + адаптер ЮKassa, checkout топ-апов/подписок, webhook со state-machine, авто-возвраты с клавбэком и billing-hold, worker-billing, админ-панель счетов. Архитектура — ARCHITECTURE.md §8a, включение — DEPLOY.md §4a.

T-E1-009 — Деплой + edge (Nginx/certbot)

Статус: done · Оценка: M · Зависимости: T-E1-007

deploy/nginx/templates/contract-check.conf.template, deploy/nginx/certbot-init.sh, DEPLOY.md §13, docker-compose.yml профиль edge.

T-E1-010a — Мониторинг: логи (Grafana + Loki + Promtail)

Статус: done · Оценка: S · Зависимости: T-E1-007

deploy/observability/loki-config.yaml, promtail-config.yaml, grafana/provisioning/{datasources,dashboards}/, grafana/dashboards/logs.json; профиль obs в docker-compose.yml поднимает loki, promtail, grafana. Promtail забирает логи всех compose-контейнеров через Docker socket и пушит в Loki; доступен дашборд Contract Check — Logs с фильтром по service и поиском по correlation_id.

T-E1-010b — Мониторинг: метрики + трейсы (Prometheus + Tempo + OTel collector + Sentry)

Статус: todo · Оценка: M · Зависимости: T-E1-010a

Добавить prometheus, tempo, otel-collector в профиль obs. Prometheus scrape :9100/:9101/:9102. OTel collector принимает OTLP и маршрутизирует в Tempo. Дашборды: queue depth, job latency, LLM tokens, credits. Sentry уже инициализируется в коде при наличии SENTRY_DSN.


Этап 2 — Веб + подписки

T-E2-001 — Миграция БД: планы и счета

Статус: todo · Оценка: M · Зависимости: T-E1-002

users.plan (free|solo|team), users.plan_renews_at. Таблица invoices уже существует (stub); наполнить логикой.

T-E2-002 — Telegram Login Widget auth

Статус: done · Оценка: M · Зависимости: T-E1-003

Реализовано в core/auth.py + api/routes/auth/telegram.py: /api/v1/auth/telegram/web и /api/v1/auth/telegram/miniapp проверяют HMAC-подпись Telegram и выдают тот же user JWT, что и бот.

T-E2-003 — React SPA (Vite)

Статус: todo · Оценка: L · Зависимости: T-E2-002

Загрузка, история, профиль, подписка. Сборка в статику; api отдаёт index.html на /.

T-E2-004 — Подписки ЮKassa recurring

Статус: todo · Оценка: M · Зависимости: T-E2-001, T-E2-003

Тарифы solo (1 490 ₽), team (3 990 ₽). Ежемесячное продление/reset.


Этап 3 — B2B API

Примечание: в текущей архитектуре B2B API строится не после веба, а поверх уже готового api и существующей очереди. Зависимость от T-E2-002 снята.

T-E3-001 — Миграция БД: api_keys и api_key_requests

Статус: done · Оценка: M · Зависимости: T-E1-002

migrations/versions/0002_api_keys.py: таблицы

  • api_keys(id, user_id FK, name, key_hash, rate_limit_rps, monthly_quota, monthly_used, resets_at, revoked, created_at, last_used_at)
  • api_key_requests(id, api_key_id FK, document_id FK, created_at) Накатывается/откатывается чисто; SQLAlchemy-модели в core/db/models.py.

T-E3-002 — Redis-клиент и token-bucket rate limiter

Статус: done · Оценка: M · Зависимости: T-E3-001

core/redis_client.py (async Redis из redis_url), core/rate_limit.py (token bucket per api_key_id, с MemoryRateLimiter-фолбэком для unit-тестов без Redis). Лимит по умолчанию = B2B_DEFAULT_RATE_LIMIT_RPS (3), переопределяется api_keys.rate_limit_rps. Покрыт tests/unit/test_rate_limit.py; 429 при превышении.

T-E3-003 — X-API-Key auth dependency

Статус: done · Оценка: M · Зависимости: T-E3-001, T-E3-002

api/deps.py: require_api_key — проверяет X-API-Key по key_hash (core/api_keys.py), отклоняет revoked, обновляет last_used_at, применяет rate-limit. api/routes/b2b.py: POST /api/v1/analyze, GET /api/v1/b2b/reports/{document_id}, GET /api/v1/b2b/usage. Покрыт tests/integration/test_b2b_api.py (вкл. 401/429).

T-E3-004 — Управление API-ключами (user JWT auth)

Статус: done · Оценка: S · Зависимости: T-E3-001

api/routes/b2b.py под user JWT auth: POST /api/v1/b2b/keys (plaintext ключ возвращается только один раз), GET /api/v1/b2b/keys, POST /api/v1/b2b/keys/{id}/revoke, GET /api/v1/b2b/keys/{id}/usage. Revoke мгновенно отключает аутентификацию.

T-E3-005 — Интеграционные тесты B2B API

Статус: done · Оценка: M · Зависимости: T-E3-003

tests/integration/test_b2b_api.py: upload → 202 → poll report; ветки 401/429. Seed API key в tests/integration/conftest.py.


Сводка порядка (обновлённая)

  1. E0 — прототип (done, кроме живых замеров T-E0-006).
  2. E1.001007 — ядро + БД + FastAPI api + worker-extract + worker-analyze + bot + Docker/compose (done).
  3. E3 — B2B API (done: миграция, rate-limit, auth, роуты, тесты).
  4. E1.008 — оплата ЮKassa (done — трек .scratch/user-profile-billing/, тикеты 001019: профили, планы/подписки, платежи, возвраты, worker-billing, админ-панель).
  5. E1.009010 — деплой/edge (Nginx/certbot — done) и observability: логи Grafana+Loki+Promtail — done, метрики/трейсы Prometheus/Tempo/OTel — todo.
  6. E2 — веб (todo; React SPA; Login Widget и подписки уже реализованы в рамках E1.008-трека).

Ближайшие работы: E1.010 (observability), затем E2 (React SPA поверх готового API).