Init
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
---
|
||||
id: 000
|
||||
title: Task format reference
|
||||
status: DONE
|
||||
created: 2026-02-01
|
||||
---
|
||||
|
||||
## Context
|
||||
В репозитории хранится эталонная задача, которая показывает обязательный формат задач.
|
||||
|
||||
## Goal
|
||||
Дать каноничный пример минимального формата задачи, обязательного для всех файлов в `spec/tasks/`.
|
||||
|
||||
## Constraints
|
||||
- Содержать только требования к формату, без продуктовой реализации.
|
||||
- Оставаться совместимой с обязательной структурой задач Planner.
|
||||
- Не добавлять требований к реализации.
|
||||
|
||||
## Acceptance criteria
|
||||
- Front matter содержит `id`, `title`, `status`, `created`.
|
||||
- Все обязательные секции присутствуют в требуемом порядке.
|
||||
- Содержимое остаётся эталонной, неисполняемой задачей.
|
||||
|
||||
## Definition of Done
|
||||
- [x] Front matter использует обязательные поля.
|
||||
- [x] Обязательные секции присутствуют.
|
||||
- [x] Файл пригоден только как reference формата.
|
||||
|
||||
## Tests
|
||||
- Runtime-тесты не требуются.
|
||||
- Формат валидируется успешной генерацией spec index.
|
||||
|
||||
## Commands
|
||||
- `python3 spec/gen_spec_index.py --check`
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
id: 001
|
||||
title: Create app skeleton and component configuration
|
||||
status: DONE
|
||||
created: 2026-03-07
|
||||
---
|
||||
|
||||
## Context
|
||||
Сейчас в репозитории есть только specification-файлы, при этом `spec/overview.md` задаёт конкретную структуру приложения и требования к конфигурации компонентов.
|
||||
|
||||
## Goal
|
||||
Создать начальный `app/` skeleton и модели конфигурации из project overview, включая отдельные секции конфигурации для Controller, Service, Business Logic, Repository, Adapter, Observability и Alerts.
|
||||
|
||||
## Constraints
|
||||
- Соблюдать layered architecture из `AGENTS.md`.
|
||||
- Scope задачи: только scaffolding и configuration, без business workflows.
|
||||
- Не реализовывать provider HTTP calls, cache behavior или aggregation logic в рамках этой задачи.
|
||||
- Не изменять файлы в `spec/`.
|
||||
|
||||
## Acceptance criteria
|
||||
- Структура `app/` создана согласно `spec/overview.md`.
|
||||
- `app/config.py` содержит отдельные component configuration sections. Config must be a .yaml-file added to .gitignore.
|
||||
- FastAPI entrypoint существует и успешно импортирует configuration.
|
||||
- В файлах Controller, Service, Repository и Adapter отсутствуют business rules.
|
||||
|
||||
## Definition of Done
|
||||
- [ ] Созданы обязательные директории `app/` и базовые файлы.
|
||||
- [ ] Реализованы раздельные секции конфигурации по компонентам.
|
||||
- [ ] Проходит app import smoke test.
|
||||
- [ ] Изменения остаются строго в scope задачи.
|
||||
|
||||
## Tests
|
||||
- Добавить/import smoke test для FastAPI app startup.
|
||||
- Добавить unit tests, проверяющие загрузку configuration sections из environment variables.
|
||||
|
||||
## Commands
|
||||
- `poetry run pytest tests/smoke/test_app_import.py -q`
|
||||
- `poetry run pytest tests/config/test_config_sections.py -q`
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
id: 002
|
||||
title: Implement pure domain quote rules
|
||||
status: TODO
|
||||
created: 2026-03-07
|
||||
---
|
||||
|
||||
## Context
|
||||
`spec/overview.md` требует business rules для фильтрации тарифов, сравнения цен, сортировки и нормализации входных данных в чистом слое Business Logic.
|
||||
|
||||
## Goal
|
||||
Реализовать детерминированные, dependency-free domain functions в `app/domain/quotes.py` для нормализации запроса и фильтрации/упорядочивания котировок.
|
||||
|
||||
## Constraints
|
||||
- Business Logic должна быть pure и dependency-free.
|
||||
- Запрещены прямые IO, adapters, repositories, framework imports и внешние вызовы.
|
||||
- Слои Service и Controller не должны забирать domain rules из этой задачи.
|
||||
- Не изменять файлы в `spec/`.
|
||||
|
||||
## Acceptance criteria
|
||||
- Domain functions нормализуют значения запроса по явным детерминированным правилам.
|
||||
- Domain functions отфильтровывают невалидные котировки по определённым domain conditions.
|
||||
- Domain functions сортируют валидные котировки по возрастанию цены.
|
||||
- Логика реализована только в `app/domain/` и доступна для вызова из Service.
|
||||
|
||||
## Definition of Done
|
||||
- [ ] Реализованы pure domain functions для normalization/filtering/sorting.
|
||||
- [ ] Поведение функций детерминированное и без side effects.
|
||||
- [ ] В domain module нет импортов не-domain зависимостей.
|
||||
- [ ] Unit tests (без mocks) покрывают стандартные и edge cases.
|
||||
|
||||
## Tests
|
||||
- Добавить `tests/domain/test_quotes.py` только с unit tests.
|
||||
- Покрыть edge cases: пустой input, невалидные quotes, одинаковые цены, границы нормализации.
|
||||
|
||||
## Commands
|
||||
- `poetry run pytest tests/domain/test_quotes.py -q`
|
||||
@@ -0,0 +1,39 @@
|
||||
---
|
||||
id: 003
|
||||
title: Add CDEK provider adapter
|
||||
status: TODO
|
||||
created: 2026-03-07
|
||||
---
|
||||
|
||||
## Context
|
||||
Phase 1 в `spec/overview.md` требует поддержку provider CDEK с OAuth2 authentication и маппингом расчёта тарифа.
|
||||
|
||||
## Goal
|
||||
Реализовать adapter interfaces и модули CDEK adapter: provider contract, OAuth2 token handling, HTTP client behavior и преобразование ответа в `DeliveryPrice`.
|
||||
|
||||
## Constraints
|
||||
- Только Adapter layer; без business decisions и sorting logic.
|
||||
- Внешний IO должен оставаться внутри adapter modules.
|
||||
- Timeout для CDEK должен быть 10 секунд согласно specification.
|
||||
- Не изменять файлы в `spec/`.
|
||||
|
||||
## Acceptance criteria
|
||||
- Существует интерфейс `DeliveryProvider` со стабильным контрактом `get_price()`.
|
||||
- Модуль CDEK auth получает OAuth2 token через client credentials и переиспользует валидный token до истечения.
|
||||
- CDEK client выполняет tariff request с timeout и retry behavior.
|
||||
- CDEK mapper преобразует provider response в унифицированную schema `DeliveryPrice`.
|
||||
- Adapter наружу предоставляет только provider-facing API, необходимый Service.
|
||||
|
||||
## Definition of Done
|
||||
- [ ] Реализован base provider interface.
|
||||
- [ ] Реализованы модули CDEK auth/client/mapper.
|
||||
- [ ] CDEK adapter возвращает унифицированную price model при успешном ответе.
|
||||
- [ ] Adapter tests покрывают auth refresh, timeout/retry и mapping cases.
|
||||
|
||||
## Tests
|
||||
- Добавить adapter unit tests для token lifecycle behavior.
|
||||
- Добавить adapter tests для response mapping и HTTP error handling.
|
||||
- Для внешних HTTP взаимодействий использовать stubs/mocks.
|
||||
|
||||
## Commands
|
||||
- `poetry run pytest tests/adapters/delivery_providers/cdek -q`
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
id: 004
|
||||
title: Add Redis price cache repository
|
||||
status: TODO
|
||||
created: 2026-03-07
|
||||
---
|
||||
|
||||
## Context
|
||||
Product requirements требуют кеширование ответов provider с configurable TTL, а архитектура закрепляет доступ к данным за слоем Repository.
|
||||
|
||||
## Goal
|
||||
Реализовать `PriceCache` repository на Redis с операциями `get`, `set` и `invalidate`, включая поддержку TTL.
|
||||
|
||||
## Constraints
|
||||
- Только Repository layer: data access и persistence mapping.
|
||||
- В repository code не допускаются business decisions и workflow orchestration.
|
||||
- Генерация cache key не должна реализовываться в repository.
|
||||
- Не изменять файлы в `spec/`.
|
||||
|
||||
## Acceptance criteria
|
||||
- Repository module существует по пути `app/repositories/cache/redis_cache.py`.
|
||||
- `PriceCache` предоставляет async методы `get`, `set`, `invalidate`.
|
||||
- `set` применяет TTL из configuration.
|
||||
- Serialization/deserialization cached payload выполняются детерминированно.
|
||||
|
||||
## Definition of Done
|
||||
- [ ] Реализован Redis-backed cache repository.
|
||||
- [ ] Интерфейс repository соответствует требуемым операциям.
|
||||
- [ ] Поведение TTL покрыто тестами.
|
||||
- [ ] В repository отсутствует business logic.
|
||||
|
||||
## Tests
|
||||
- Добавить repository tests для cache hit/miss, set/get roundtrip, invalidate и TTL expiration.
|
||||
- Использовать Redis test double или изолированный test Redis instance.
|
||||
|
||||
## Commands
|
||||
- `poetry run pytest tests/repositories/cache/test_redis_cache.py -q`
|
||||
@@ -0,0 +1,39 @@
|
||||
---
|
||||
id: 005
|
||||
title: Implement aggregator service workflow
|
||||
status: TODO
|
||||
created: 2026-03-07
|
||||
---
|
||||
|
||||
## Context
|
||||
`spec/overview.md` определяет `AggregatorService.get_all_prices()` как application orchestrator для параллельных provider calls, graceful degradation, caching и отсортированного унифицированного результата.
|
||||
|
||||
## Goal
|
||||
Реализовать `AggregatorService.get_all_prices(request: DeliveryRequest) -> list[DeliveryPrice]` в `app/services/aggregator.py` с параллельным выполнением, cache coordination и делегированием business rules в domain functions.
|
||||
|
||||
## Constraints
|
||||
- Service выполняет только orchestration; pure business rules остаются в Business Logic.
|
||||
- Использовать dependency injection для providers и repository.
|
||||
- Для вызовов providers использовать `asyncio.gather(..., return_exceptions=True)`.
|
||||
- Не изменять файлы в `spec/`.
|
||||
|
||||
## Acceptance criteria
|
||||
- Service вызывает все зарегистрированные providers параллельно.
|
||||
- Failures/timeouts отдельных providers не валят весь запрос; упавшие providers исключаются.
|
||||
- Cache проверяется до внешнего provider request и обновляется после успешного provider response.
|
||||
- Фильтрация/сортировка котировок делегируется domain functions.
|
||||
- Возвращаемый список котировок унифицирован и отсортирован по цене по возрастанию.
|
||||
|
||||
## Definition of Done
|
||||
- [ ] Метод Service реализован с injected dependencies.
|
||||
- [ ] Параллельная orchestration использует `return_exceptions=True`.
|
||||
- [ ] Реализована cache coordination для provider responses.
|
||||
- [ ] Service tests покрывают full-success, partial-failure, all-failure и cache-hit сценарии.
|
||||
|
||||
## Tests
|
||||
- Добавить service tests со stubs/mocks для adapters и repository.
|
||||
- Проверить orchestration и исключение неуспешных providers.
|
||||
- Проверить делегирование sorting/filtering в domain logic.
|
||||
|
||||
## Commands
|
||||
- `poetry run pytest tests/services/test_aggregator.py -q`
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
id: 006
|
||||
title: Add delivery price controller endpoint
|
||||
status: TODO
|
||||
created: 2026-03-07
|
||||
---
|
||||
|
||||
## Context
|
||||
API contract требует endpoint `POST /api/v1/delivery/price` с DTO validation и HTTP error mapping, при этом Controller должен вызывать ровно один метод Service.
|
||||
|
||||
## Goal
|
||||
Реализовать request/response schemas и endpoint в `app/controllers/v1/delivery.py`, который валидирует входные данные, делегирует в `AggregatorService.get_all_prices()` и маппит service exceptions в HTTP responses.
|
||||
|
||||
## Constraints
|
||||
- Controller не должен содержать business logic или provider-specific branching.
|
||||
- На каждый запрос Controller должен вызывать ровно один метод Service.
|
||||
- Validation должна использовать Pydantic models из schema layer.
|
||||
- Не изменять файлы в `spec/`.
|
||||
|
||||
## Acceptance criteria
|
||||
- `POST /api/v1/delivery/price` принимает payload `DeliveryRequest` и возвращает `list[DeliveryPrice]`.
|
||||
- Невалидный input возвращает validation error response.
|
||||
- Controller делегирует обработку в `AggregatorService.get_all_prices()`.
|
||||
- Service exceptions маппятся в детерминированные HTTP responses.
|
||||
|
||||
## Definition of Done
|
||||
- [ ] Реализованы request и response schemas.
|
||||
- [ ] Controller endpoint подключён в FastAPI router.
|
||||
- [ ] Path и HTTP method endpoint соответствуют specification.
|
||||
- [ ] API tests покрывают успешный ответ, validation failure и mapped service error.
|
||||
|
||||
## Tests
|
||||
- Добавить controller tests для поведения route и делегирования в service.
|
||||
- Добавить API-level tests для валидации request schema и response schema.
|
||||
|
||||
## Commands
|
||||
- `poetry run pytest tests/controllers/v1/test_delivery.py -q`
|
||||
@@ -0,0 +1,41 @@
|
||||
---
|
||||
id: 007
|
||||
title: Add observability correlation and telemetry
|
||||
status: TODO
|
||||
created: 2026-03-07
|
||||
---
|
||||
|
||||
## Context
|
||||
Проект требует связать traces, metrics и logs через request correlation (`request_id` и `trace_id`) и добавить manual spans вокруг ключевых операций.
|
||||
|
||||
## Goal
|
||||
Реализовать observability wiring: middleware для `request_id`, propagation structured logging context, OpenTelemetry instrumentation для FastAPI/httpx и manual spans для операций service/provider/cache.
|
||||
|
||||
## Constraints
|
||||
- Все observability concerns держать вне Business Logic.
|
||||
- При добавлении telemetry не вводить business decision-making.
|
||||
- Инструментировать только слои и операции, указанные в `spec/overview.md`.
|
||||
- Не изменять файлы в `spec/`.
|
||||
|
||||
## Acceptance criteria
|
||||
- Middleware назначает UUID `request_id` для каждого запроса.
|
||||
- `request_id` добавляется в structured logs через contextvars.
|
||||
- Включена OpenTelemetry instrumentation для FastAPI и httpx.
|
||||
- Есть manual spans для `AggregatorService.get_all_prices`, provider `get_price` и cache operations.
|
||||
- Span attributes включают `provider`, `from_city`, `to_city`, `weight_kg`, `cache_hit`, `tariffs_found` там, где применимо.
|
||||
|
||||
## Definition of Done
|
||||
- [ ] Реализован middleware корреляции запросов.
|
||||
- [ ] В logging context есть binding `request_id`.
|
||||
- [ ] Реализована автоматическая и manual tracing instrumentation.
|
||||
- [ ] Observability tests проверяют создание spans и обязательные attributes.
|
||||
|
||||
## Tests
|
||||
- Добавить middleware tests для генерации и propagation `request_id`.
|
||||
- Добавить telemetry tests с in-memory span exporter для проверки names/attributes.
|
||||
- Добавить logging tests, проверяющие наличие `request_id` в log context.
|
||||
|
||||
## Commands
|
||||
- `poetry run pytest tests/controllers/test_middleware_request_id.py -q`
|
||||
- `poetry run pytest tests/observability/test_tracing.py -q`
|
||||
- `poetry run pytest tests/observability/test_logging_context.py -q`
|
||||
@@ -0,0 +1,41 @@
|
||||
---
|
||||
id: 008
|
||||
title: Add SigNoz to Telegram alerting configuration
|
||||
status: TODO
|
||||
created: 2026-03-07
|
||||
---
|
||||
|
||||
## Context
|
||||
`spec/overview.md` требует anomaly alerting через цепочку `SigNoz Alert Rules -> Webhook -> Telegram Bot API` с вынесением token в configuration.
|
||||
|
||||
## Goal
|
||||
Добавить configuration и infrastructure artifacts, необходимые для маршрутизации anomaly alerts из SigNoz в Telegram и для соответствия alert thresholds требованиям проекта.
|
||||
|
||||
## Constraints
|
||||
- Alert transport/configuration должны быть отделены от business logic.
|
||||
- Telegram credentials должны приходить из configuration и не быть hardcoded.
|
||||
- Thresholds должны соответствовать alert conditions из `spec/overview.md`.
|
||||
- Не изменять файлы в `spec/`.
|
||||
|
||||
## Acceptance criteria
|
||||
- Configuration содержит отдельную секцию Alerts с Telegram settings.
|
||||
- Infrastructure artifact(s) описывают routing от SigNoz alert webhook к Telegram Bot API.
|
||||
- Представлены alert conditions для:
|
||||
- provider 5xx: 5 ошибок за 5 минут
|
||||
- provider p99 latency > 5000ms в течение 10 минут
|
||||
- provider unavailable более 5 минут
|
||||
- Setup instructions содержат обязательные environment variables и шаги верификации.
|
||||
|
||||
## Definition of Done
|
||||
- [ ] Реализована schema конфигурации Alerts.
|
||||
- [ ] Добавлены artifact(s) для маршрутизации SigNoz-to-Telegram.
|
||||
- [ ] Определены все три обязательных anomaly conditions.
|
||||
- [ ] Инструкции валидации исполнимы в local environment.
|
||||
|
||||
## Tests
|
||||
- Добавить config tests для проверки загрузки alert settings и обязательных полей.
|
||||
- Добавить tests для alert payload transformation/transport logic, если он реализован в коде.
|
||||
|
||||
## Commands
|
||||
- `poetry run pytest tests/config/test_alerts_config.py -q`
|
||||
- `docker compose config`
|
||||
@@ -0,0 +1,39 @@
|
||||
---
|
||||
id: 009
|
||||
title: Add local infrastructure stack
|
||||
status: TODO
|
||||
created: 2026-03-07
|
||||
---
|
||||
|
||||
## Context
|
||||
Overview задаёт локальные infrastructure components `app`, `redis` и `signoz`, необходимые для runtime и observability.
|
||||
|
||||
## Goal
|
||||
Добавить Docker Compose infrastructure definitions для local development, включая application service, Redis cache и SigNoz observability backend.
|
||||
|
||||
## Constraints
|
||||
- Scope задачи: только infrastructure wiring.
|
||||
- Не переносить business logic в infrastructure scripts.
|
||||
- Имена services должны соответствовать overview: `app`, `redis`, `signoz`.
|
||||
- Не изменять файлы в `spec/`.
|
||||
|
||||
## Acceptance criteria
|
||||
- Compose file определяет services `app`, `redis`, `signoz`.
|
||||
- Service `app` содержит environment wiring для cache и observability endpoints.
|
||||
- Service `redis` достижим из `app` во внутренней сети.
|
||||
- Service `signoz` достижим для telemetry export при локальном запуске.
|
||||
|
||||
## Definition of Done
|
||||
- [ ] Добавлен compose definition с обязательными services.
|
||||
- [ ] Задокументированы environment variables для локальной интеграции.
|
||||
- [ ] `docker compose config` проходит валидацию.
|
||||
- [ ] Добавлены базовые startup instructions.
|
||||
|
||||
## Tests
|
||||
- Добавить/обновить infrastructure checks для валидации compose syntax.
|
||||
- Добавить smoke sequence команд для проверки локального запуска.
|
||||
|
||||
## Commands
|
||||
- `docker compose config`
|
||||
- `docker compose up -d redis signoz`
|
||||
- `docker compose ps`
|
||||
Reference in New Issue
Block a user