github MBombeck/HealthLog v1.4.38.2
v1.4.38.2 — Mood-reminder hotfix bundle + Settings toggle

latest releases: v1.4.38.4, v1.4.38.3
6 hours ago

Mood-reminder hotfix bundle on top of v1.4.38.1 plus the missing Settings toggle. A six-axis review of the v0.5.4 iOS-coordination patch surfaced enough real blockers that the mood-reminder feature could not have been used safely as shipped.

Added

  • Settings toggle for the daily mood reminder — new card under /settings/notifications with a single Switch wired to the user profile flag. Six-locale copy (de/en/es/fr/it/pl) for the title, description, status text, and toasts. Without this surface the feature shipped in v1.4.38.1 was unreachable for end users.
  • DispatchOutcome return type on dispatchNotification so callers can decide whether the send is committed to their own ledger. Existing callers ignore the return and keep working — the function is still best-effort and never throws.
  • localHmAsUtc helper returns the UTC instant of local hh:mm on the local calendar day implied by now. Re-derives the offset at the target local time so the result stays correct on DST transition days.
  • Daily 03:25 Europe/Berlin retention sweep for the mood_reminder_dispatches ledger: deletes rows older than 90 days.

Fixed

  • Mood-reminder ledger writes only after the dispatcher confirms delivery. A dispatched = false outcome (no channel succeeded) leaves the slot empty so the next tick is free to retry once the user adds a channel or upstream recovers.
  • Mood-reminder locale resolver honours every supported locale. v1.4.38.1 shipped translations for es/fr/it/pl but the resolver silently demoted those users to English copy.
  • Mood-reminder FR body restores the apostrophe in aujourd'hui. v1.4.38.1 shipped without it; VoiceOver reads the lockscreen body aloud, so the typo was audible.
  • Medication-reminder scheduledFor and the iOS-snooze scheduledAt ISO are now DST-safe. The previous arithmetic added raw UTC hours to local midnight and drifted by an hour on spring-forward / fall-back days.
  • Per-user try wrapper around the mood-reminder tick. A single bad row (corrupt timezone, dispatcher exception) used to abort the whole 22:00 candidate pass; now the wide-event records a per-user failure counter and the rest of the cohort is unaffected.
  • APNs payload whitelists iOS-relevant metadata keys. The dispatcher's metadata field is shared across every channel and was forwarding channel-specific payload structures (Telegram's replyMarkup inline-keyboard object, ad-hoc extras) into the APNs userInfo Apple sees plus the iOS notification handler. Allowlist now covers only what iOS actually reads.

Refactor

  • Dead MoodReminderCandidate interface dropped + redundant select field removed (the where clause already filters to opted-in users).
  • CHANGELOG entry for v1.4.38.1 rewritten to drop the EVENT_DEFAULT_ENABLED identifier reference and describe the default-off posture in user-readable language.

Tests

  • Unit suite 4565 → 4551 (rewrote mood-reminder.test.ts for the new contract; net delta is a rewrite, not a coverage loss). Added tests for ledger-after-delivery semantics, per-user try wrapper, P2002-race semantics, six-locale dispatch, and the FR apostrophe regression.

Operator notes

  • No new migration. No env-var change.
  • Coolify auto-deploys main on tag push; first webhook may pull stale :latest, redeploy after the docker-publish workflow completes.

Don't miss a new HealthLog release

NewReleases is sending notifications on new releases.