Closes the unpinned-deps gotcha that broke production once already (Starlette 1.0 shipping in 2026-04 changed the TemplateResponse signature; our floating requirements.txt picked it up on the next rebuild and the dashboard 500'd until 1.0.0-12 patched the call sites). Mechanics: * `requirements.in` — human-edited input, identical contents to the old `requirements.txt`. * `requirements.txt` — now an autogenerated lockfile (876 lines, every transitive pinned with sha256 hashes). Regenerated via `scripts/regenerate-lockfile.sh`, which runs `pip-compile --generate-hashes --strip-extras` in a clean python:3.12-slim container so the script has no host dependencies. * Dockerfile installs with `pip install --require-hashes` — refuses any package whose sha256 doesn't match the lockfile, defending against compromised PyPI mirrors and accidental version drift. Verification: * Container boots clean on the hash-locked install (1.0.0-25). * /health returns 200 with all checks green. * Daily security scan (pip-audit + bandit + gitleaks) returns 0 findings against the new lockfile. Future deps changes: edit requirements.in, run the regenerate script, review the diff, rebuild, commit both files. README §"Updating dependencies" walks through it. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
22 lines
728 B
Text
22 lines
728 B
Text
# Human-edited dependency input.
|
|
# requirements.txt is a fully-pinned lockfile generated from THIS file
|
|
# via scripts/regenerate-lockfile.sh — never edit requirements.txt by
|
|
# hand. Add/remove deps here, then re-run the script.
|
|
#
|
|
# Why a lockfile: starlette 1.0 shipping in 2026-04 broke the dashboard
|
|
# because requirements.txt had no upper bounds and the next rebuild
|
|
# pulled the breaking version (TemplateResponse signature change). The
|
|
# lockfile + --require-hashes in the Dockerfile makes the build fully
|
|
# reproducible AND defends against compromised upstream mirrors.
|
|
|
|
fastapi
|
|
uvicorn[standard]
|
|
aiosqlite
|
|
httpx
|
|
pydantic-settings
|
|
jinja2
|
|
sse-starlette
|
|
asyncssh
|
|
itsdangerous>=2.1
|
|
bcrypt>=4.0,<5.0
|
|
python-multipart>=0.0.7
|