Previously /config accepted any value and called ESP.restart() — fuzz tests
(or any malicious POST) could save garbage SSIDs and brick the device until
FTDI recovery. Now:
- SSID: rejected if empty, >31 chars, non-printable, or all-same-char (HTTP 400)
- Password: rejected if >63 chars
- Hostname/city_name/ntp_server: length-validated
- Numeric fields (timezone, brightness, intervals, lat/lon, display): clamped
to safe ranges via constrain()
Tested on hardware: ssid="AAAA..." now correctly returns HTTP 400 and
preserves existing config. Device survives entire fuzz suite.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
docs/v1.9_RELEASE_NOTES.md, v1.9.1_HYBRID_FIX.md, v1.9.2_WIFI_RESILIENCE.md
were internal working documents (incomplete checklists, dev notes).
CHANGELOG.md already covers all versions — links removed, status updated to v1.9.3.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>