# Итоги: закрепление версий зависимостей (п. 1.2) План: `docs/plan-pin-dependencies.md`. ## Сделано - `requirements.txt` и `requirements-dev.txt`: прямые зависимости с точными версиями. Прод: `requests==2.34.2`, `fastapi==0.141.1`, `uvicorn==0.53.0`, `APScheduler==3.11.3`. Разработка: `pytest==9.1.1`, `httpx==0.28.1`. - `constraints.txt` (новый, 26 пакетов): полный `pip freeze` образа, на котором проходили тесты, включая транзитивные пакеты (`starlette`, `pydantic`, `urllib3` и др.). - `Dockerfile` и `Dockerfile.test` ставят пакеты с `-c constraints.txt`. - README: ручная установка с `-c constraints.txt`, список копируемых файлов приведён в соответствие с кодом (был неполным), раздел «Dependency versions» с порядком обновления, замечание об образе исправлено. ## Проверка - Оба образа собраны без кэша, 18 тестов проходят. - Прод-образ: пакеты полностью совпадают с `constraints.txt`, `pytest` и `httpx` в нём нет; `api_server`, `collector_daemon`, `db`, `healthcheck` импортируются. - Версии взяты из того, что уже стояло и проходило тесты, поведение не менялось. ## Замечания - Базовый образ `python:3.11-slim` не закреплён по дайджесту: патчи Python приходят при пересборке (осознанный компромисс). - Закрепление даёт воспроизводимость, но не обновляет уязвимые версии само: проверку обновлений нужно делать вручную (порядок в README). - Не проверялась сборка на другой архитектуре: часть пакетов (`pydantic_core`) содержит бинарные сборки под платформу. - `docker compose up` не запускался повторно: образ собран тем же Dockerfile, стенд не менялся.