master/tasks.md

142 lines
11 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.

# План работ: web-python-skelet
## Контекст
- Источник требований: `AGENTS.md` и ADR `docs/001`-`docs/004`
- Текущее состояние: в `adapter/`, `domain/`, `usecase/`, `repository/`, `test/` пока только `__init__.py`
- Отсутствуют рабочие каталоги и файлы из целевой структуры: `adapter/config/`, `adapter/otel/`, `adapter/di/`, `adapter/http/fastapi/`, `config/`, `main.py`
- Ограничения: `docs/` и `tasks.md` не добавлять в git; коммиты не делать; работать по одной задаче
- ADR пока покрывают архитектуру, новые ADR нужны только если по ходу работ изменится решение
## Правила выполнения
- Каждую задачу выполнять отдельным заходом, без параллельной реализации
- Каждый субагент отдает diff, список измененных файлов и проверку, но не делает commit
- Если в задаче всплывает архитектурное изменение, остановиться и вынести вопрос на согласование
## Очередь задач
### T01. Базовый каркас домена и usecase
- Исполнитель: `primary-agent` (scaffolding)
- Статус: completed
- Зависимости: нет
- Commit required: no
- Scope: создать базовые файлы и контракты в `domain/`, `usecase/`, `repository/`
- Файлы: `domain/error.py`, `domain/user.py`, `usecase/interface.py`, `usecase/user.py`, `repository/user.py`
- Критерии приемки: зависимости направлены внутрь; в `domain/` и `usecase/` нет FastAPI/OTel; есть пример сущности, ошибок, портов и простого usecase
### T02. Конфиг из YAML и env
- Субагент: `feature-developer`
- Статус: completed
- Зависимости: `T01`
- Commit required: no
- Scope: собрать typed-config слой в `adapter/config/` и подготовить базовые yaml-файлы
- Файлы: `adapter/config/*`, `config/app.yaml`
- Критерии приемки: конфиг собирается в одну dataclass-структуру; секреты читаются из env; парсинг и валидация не протекают в inner layers
### T03. Observability порты и OTel adapter
- Субагент: `feature-developer`
- Статус: completed
- Зависимости: `T01`, `T02`
- Commit required: no
- Scope: реализовать логгер, метрики, трейсинг и bootstrap OTel в `adapter/otel/` через интерфейсы из `usecase/interface.py`
- Файлы: `adapter/otel/*`, `config/otel-collector.yaml`
- Критерии приемки: inner layers знают только интерфейсы; OTLP exporter настраивается из конфига; нет кастомного trace middleware
### T04. Composition root и lifetime singleton-объектов
- Субагент: `feature-developer`
- Статус: completed
- Зависимости: `T01`, `T02`, `T03`
- Commit required: no
- Scope: собрать контейнер и startup wiring в `adapter/di/`
- Файлы: `adapter/di/container.py`, `adapter/di/__init__.py`
- Критерии приемки: repository/usecase создаются один раз на старте; контейнер хранит инстансы явно; нет пересоздания на HTTP-запрос
### T05. FastAPI adapter как заменяемый web layer
- Субагент: `feature-developer`
- Статус: completed
- Зависимости: `T04`
- Commit required: no
- Scope: поднять HTTP adapter в `adapter/http/fastapi/` с app factory, lifespan, dependencies, middleware и router ` /api/v1`
- Файлы: `adapter/http/fastapi/*`, `main.py`
- Критерии приемки: FastAPI изолирован в adapter-слое; handlers тонкие; request logging и metrics middleware подключены; usecase/repository берутся из контейнера
### T06. Локальный runtime и compose-окружение
- Субагент: `feature-developer`
- Статус: completed
- Зависимости: `T02`, `T03`, `T05`
- Commit required: no
- Scope: добавить контейнерный runtime для сервиса и compose-окружение с OTel и UI для просмотра логов, метрик и трейсов
- Файлы: `Dockerfile`, `docker-compose.yml`
- Ограничения: не трогать репозиторный `config/app.yaml`; docker должен прокидывать свой runtime-config внутрь контейнера; Dockerfile только с двумя стадиями `build` и `run`
- Критерии приемки: `make compose-build` и `make compose-up` опираются на существующие файлы; сервис поднимается в контейнере; OTel telemetry уходит в dockerized stack; есть UI для просмотра логов, метрик и трейсов; для локального docker-окружения достаточно только `Dockerfile` и `docker-compose.yml`
### T07. Тесты на lifetimes, config и HTTP smoke
- Субагент: `test-engineer`
- Статус: pending
- Зависимости: `T01`, `T02`, `T03`, `T04`, `T05`, `T06`
- Commit required: no
- Scope: покрыть тестами ключевые архитектурные гарантии
- Файлы: `test/*`
- Критерии приемки: есть тест на singleton lifetime для repository/usecase; есть тест merge YAML+env; есть smoke-тест для ` /api/v1`; тесты не тянут FastAPI/OTel в inner layers
### T08. Архитектурный и boundary review
- Субагент: `code-reviewer`
- Статус: pending
- Зависимости: `T07`
- Commit required: no
- Scope: проверить импорты, соблюдение слоев, startup lifetimes и заменяемость web adapter
- Файлы: весь измененный код
- Критерии приемки: dependency direction не нарушен; FastAPI и OTel не протекают в `domain/` и `usecase/`; замечания сформулированы как точечные правки или подтверждение готовности к review
### T09. Конфигурируемый runtime observability
- Субагент: `feature-developer`
- Статус: completed
- Зависимости: `T03`, `T04`, `T05`
- Commit required: no
- Scope: сделать конфигурируемый runtime observability с настраиваемым sink и форматом логов, плюс отдельными флагами для метрик и трейсов
- Файлы: `adapter/config/*`, `adapter/observability/*`, `adapter/otel/*`, `adapter/di/*`, `adapter/http/fastapi/*`, `config/app.yaml`, при необходимости `main.py`
- Конфиг: `logging.output=stdout|file|otel`, `logging.format=text|json`, `logging.file_path=...`, `metrics.enabled=true|false`, `tracing.enabled=true|false`
- Решение: вынести выбор runtime в отдельный adapter-layer factory; `domain/` и `usecase/` не менять; для `stdout` и `file` поддержать оба формата `text` и `json`; `logging.file_path` использовать только при `logging.output=file`; при отключенных метриках и трейсах использовать `Noop`-реализации; OTel runtime поднимать только если нужен хотя бы для одного сигнала
- Критерии приемки: при `logging.output=stdout` логи идут в stdout в формате `text` или `json` по конфигу; при `logging.output=file` логи пишутся в файл по пути `logging.file_path` в формате `text` или `json`; при `logging.output=otel` логи уходят в collector; `metrics.enabled=false` отключает метрики и metrics middleware; `tracing.enabled=false` отключает FastAPI instrumentation и tracer runtime; DI продолжает отдавать единый runtime через контейнер; внутренние слои по-прежнему знают только порты
### T10. ADR: раннее подключение OTel к FastAPI
- Исполнитель: `primary-agent` (docs)
- Статус: completed
- Зависимости: нет
- Commit required: no
- Scope: зафиксировать правило, что FastAPI OTel instrumentation выполняется до первой сборки `middleware_stack`
- Файлы: `docs/005-fastapi-otel-early-instrumentation.md`
- Критерии приемки: ADR занимает 10-20 строк; описаны context, decision, consequences; решение не переписывает историю прошлых ADR
### T11. Перенос FastAPI OTel bootstrap в app factory
- Субагент: `feature-developer`
- Статус: completed
- Зависимости: `T10`
- Commit required: no
- Scope: перенести создание container, установку `FastAPIInstrumentor.instrument_app(...)` из `lifespan` в `create_app`, оставив в `lifespan` только shutdown
- Файлы: `adapter/http/fastapi/app.py`, `adapter/http/fastapi/lifespan.py`, при необходимости `adapter/http/fastapi/dependencies.py`
- Ограничения: не использовать ручной rebuild `app.middleware_stack`; не менять `domain/` и `usecase/`; не добавлять бизнес-логику; сохранить singleton-lifetime container
- Критерии приемки: instrumentation происходит до первой сборки middleware stack; `OpenTelemetryMiddleware` попадает в runtime stack без workaround; shutdown закрывает instrumentation и runtime один раз; compose-конфиг продолжает работать
### T12. Регрессионная проверка HTTP telemetry wiring
- Субагент: `test-engineer`
- Статус: pending
- Зависимости: `T11`
- Commit required: no
- Scope: добавить проверку, что раннее instrumentation wiring сохраняется и не требует ручного rebuild middleware stack
- Файлы: `test/*`
- Ограничения: без реального collector; проверять через ASGI/lifespan или локальные assertions по app runtime; не тянуть FastAPI и OTel в inner-layer тесты
- Критерии приемки: тест подтверждает, что при включенных metrics/tracing `OpenTelemetryMiddleware` присутствует в runtime stack; тест не зависит от внешнего OTel collector; существующие архитектурные границы не нарушены