1. Switch str_contains() to exact match ($path === $route) in PUBLIC_ROUTES check
to prevent substring-based route bypass attacks.
2. Remove blanket /api/admin/ bypass that was letting all admin endpoints through
without authentication.
3. Add requireCronSecret() — cron/scheduled task endpoints now require a valid
X-Cron-Secret header matching the PAYFRIT_CRON_SECRET env var. Uses
hash_equals() for timing-safe comparison. Applied to:
- cron/expireStaleChats.php
- cron/expireTabs.php
- api/admin/scheduledTasks/runDue.php