- import-photo.sh: validate \$SLUG against ^[a-z0-9-]+\$ before
writing under content/photography/; rejects '../' and other
surprises early. Also fail loudly with a clear message if either
'magick' resize or 'magick mogrify -strip' returns non-zero
(prevents shipping a file that still carries EXIF when the strip
silently failed).
- compress-assets.sh: reject non-numeric MIN_SIZE up front (otherwise
the comparison fails later with a cryptic arithmetic error).
- extract-dimensions.py / extract-exif.py / extract-palette.py:
add traceback.print_exc() after the broad except so a corrupt
image produces a stack trace alongside the one-line summary.
- extract-exif.py: switch from Pillow's deprecated _getexif() to
the public getexif() API; pyproject allows Pillow up to 12 where
_getexif may be removed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add tools/model-checksums.sha256 with sha256 hashes for the five
Xenova/all-MiniLM-L6-v2 files served from static/models/.
download-model.sh was already plumbed to verify against this file
when present; the file itself was missing, so downloads were
unverified. Now every fetch checks against committed hashes and
fails closed on mismatch.
- Pin embed.py's SentenceTransformer load to a specific HF commit
(c9745ed1d9f207416be6d2e6f8de32d1f16199bf of
sentence-transformers/all-MiniLM-L6-v2). A future model bump can no
longer silently change embedding semantics across builds. Bump
deliberately when validating; re-run a full embed pass to refresh
the semantic + similar-links data.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>