The auto-login route needs these fields to populate the session, but the
query only selected id, username, household_id. Added JOIN with
households table and selected is_admin + household_name.
- ntfy.py: switch from JSON body to HTTP headers (Title, Priority, Tags,
Actions, Click) with plain message body. ntfy servers treat the POST
body as the message, so JSON body fields were ignored and displayed as
raw JSON.
- ntfy.py: replace em dashes in headers with hyphens (HTTP headers must
be latin-1 encodable).
- meals.py: add /auto-login/<token> route that logs users in via their
ntfy callback token so clicking a notification opens the dashboard
without re-entering credentials.
- ntfy.py: update Click URL to /auto-login/<token>?date=...
Add .manage-form label styling and .manage-form input[type="text"] rule
to match the existing password input styling, so the ntfy topic URL field
looks consistent with the rest of the UI.
- meal-cron now runs send_reminders_cron.sh (simple wget loop, no DB mount)
- New /api/cron-tick endpoint handles all timezone logic server-side
- base_url captured from request.host_url when user saves ntfy settings,
stored per-user — no APP_BASE_URL env var needed
- Cron endpoint protected by CRON_SECRET shared env var
- Removed send_reminders_cron.py, DB volume from cron container
- tests: 3 new cron-tick + base_url capture tests (69 total)
- docker-compose.yml: meal-cron service loops send_reminders_cron.py every 60s
- send_reminders_cron.py: checks each household's local time, sends ntfy
reminders at 10:00 (lunch) and 16:00 (dinner), guarded against duplicates
- models.py: timezone, last_lunch_reminder, last_dinner_reminder on households
- meals.py: /admin/timezone route for admins to set household timezone
- dashboard: timezone selector (20 common zones) in Account Settings
- i18n: 5 new translation keys for timezone strings
- Dockerfile: copy send_reminders_cron.py
- tests: 4 new timezone tests (admin set, non-admin denied, default UTC, auth)
- docs: updated AGENTS.md