3. Dependency management: ranges + hashed lockfile¶
- Status: Accepted
- Date: 2026-06-23
Context¶
The project is consumed both as a library (pip install) and deployed as an
application (Docker). Libraries want flexible version ranges to avoid conflicts
for downstream consumers; deployments want exact, reproducible, verifiable
dependencies.
Decision¶
- Keep flexible lower-bound ranges (
>=) inpyproject.tomlfor library consumers. - Generate two universal, hashed lock files with
make lock:requirements.lock(all extras; CI and local development) andrequirements-prod.lock(runtime +llm+odbc; the Docker image). - Install from the locks with
--require-hashes(uv pip sync) in CI and in the Dockerfile builder stage; never resolve from ranges in a deployment. - Migrated the Gemini provider off the EOL
google-generativeaiSDK togoogle-genai. - Dependabot keeps both Python deps and the SHA-pinned GitHub Actions current.
Consequences¶
- Library consumers retain resolution flexibility; deployments are deterministic and tamper-evident (hashes).
- Both lock files must be regenerated (
make lock) wheneverpyproject.tomldependencies change; CI installs from them, so a stale lock fails fast.
Addendum (1.0.0)¶
The two hashed lock files became one uv.lock (ADR-0010): make lock runs uv lock, and CI
and the Dockerfile install with uv sync --frozen, which checks every hash. Dependabot is not
configured in this repository.