Harden before going public
Five fixes from the pre-publish review:
1. PROPFIND XML: escape `<D:displayname>` values (bookhive filenames and
local file names). Unescaped `&`/`<` would break the response XML for
any book with those chars in its title, and authenticated clients
could poison directory listings by PUT-ing crafted filenames.
2. Passthrough path check: replace str.startswith with is_relative_to so
a sibling directory sharing a prefix with $PASSTHROUGH_ROOT can't be
reached via `../sibling`.
3. Cover-download SSRF guard: require https + reject localhost and
RFC1918 / loopback / link-local IPs before fetching a URL returned
by the bookhive catalog.
4. Dockerfile: run as UID 10001 (non-root).
5. docker-compose: bind port to 127.0.0.1 by default, with a comment
explaining when to switch to 0.0.0.0.
New tests/test_security_guards.py covers all three code-level fixes.
Full suite: 68 passed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>