142 lines
11 KiB
Markdown
142 lines
11 KiB
Markdown
# План работ: 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; существующие архитектурные границы не нарушены
|