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>
First operator-facing README. Covers quick start (build, configure,
first-user login), the multi-drive batch workflow with concrete time
estimates, the four drive-lock states with their confirm tokens,
notable settings, daily report / notifications, ops cookbook (logs,
user CLI, backups, /health probe, DB reset), and an honest "known
gaps" list.
Cross-references CLAUDE.md (architecture + rationale) and SPEC.md
(per-version feature reference) for deeper docs.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>