Stable twin of #1253. This branch has only the publish door —
send-gallery-email is #1235, main-only — so the same gap exists here in one
place rather than two.
/publish re-hashes password_hash from a plaintext the admin re-types in the
publish dialog, validated with nothing but express-validator's
isLength({min:6}). So the configured complexity — moderate by default,
meaning 8 characters plus upper, lower and a digit — governed event creation
and password reset while this door accepted 'aaaaaa' and made it the live
gallery password.
Not an escalation: it needs admin auth plus events.edit. It is a policy gap,
the admin UI advertising a complexity level this write path did not enforce.
BEHAVIOUR CHANGE: an API-only consumer publishing with a sub-policy password
now gets 400, with the same body shape event creation returns (error,
details, score, feedback).
3 tests, including that the rejection happens BEFORE the write — the gallery
keeps its old hash and stays a draft — and that a publish carrying no
password at all is untouched.
Co-authored-by: Paul Nothaft <[email protected]>