register.php was a fully open signup form with no bot defenses — the
likely source of the unconfirmed accounts piling up in admin/users.php.
- Add an always-on honeypot field + timing trap to register.php: either
tripping silently pretends success without creating an account, so a
bot doesn't learn it was caught. No configuration needed.
- Add optional Google reCAPTCHA v3 support (includes/recaptcha.php,
recaptcha_enabled()/verify_recaptcha(), no Composer dependency — a
raw file_get_contents() POST like mailer.php's SMTP socket approach).
A failed check here shows a real, visible error instead of the silent
honeypot path, since a legitimate low-score user deserves a retry.
- Configure it through admin/settings.php's new "Bot Protection" section,
mirroring the existing SMTP pattern exactly: recaptcha_enabled/
recaptcha_site_key/recaptcha_secret_key in site_settings, secret key
masked the same way smtp_pass now is (blank submission keeps it
unchanged). install.php seeds sane defaults so the feature stays off
until explicitly configured — fully backward compatible.
- Add cron/cleanup_unconfirmed.php: deletes accounts still unconfirmed
after 3 days. CLI-only (refuses to run over HTTP, and cron/.htaccess
denies web access to the directory as a second layer) since it's an
unattended, irreversible deletion. Safe by construction — login.php
already refuses login to unconfirmed accounts, so these rows can never
own a session/novena_group/custom_prayer row. Not wired up
automatically; README documents the Hostinger cron job to schedule it.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>