github MBombeck/HealthLog v1.4.37
v1.4.37 — Final web polish before iOS focus

one hour ago

Highlights

The closing web release before the v1.5 iOS-app sprint. Carries the v1.4.36 performance carry-over for the full /api/analytics route, consolidates Apple Health step samples into one daily row per day, restores IntakeHistoryListV2 to its pre-v1.4.28 contract, converges every Coach affordance behind a single feature gate, lifts the Mounjaro medication card to byte-equivalent parity with Ramipril, hardens the client-IP source chain behind a new env flag, ships the doctor-report as a hero card under Settings → Export, adds a medication-intake quick-add overlay to the dashboard, drops the timezone override for a silent browser-zone auto-seed, and fixes the v1.4.36 red CI workflows. Documentation refreshed across all three repos with five new architecture diagrams in the Dracula palette.

Performance

  • Full /api/analytics route on the rollup-coverage probe. Correlations, healthScore and bp_in_target each gained a rollup-fast-path that fires whenever every logged type has DAY coverage, with the live SQL path remaining the source of truth for partial-coverage accounts. Cold worst-case 111 s → ~1.5–3 s on power-user accounts. Per-branch path:"rollup"|"live" annotate in the meta dict proves which branch fired.
  • Apple Health step consolidation. New groupBy=day + dayKey modes on GET /api/measurements collapse the per-sample step rows into one daily total per row with a chevron drill-down. A nightly drainPerSampleCumulative pg-boss job at 03:45 Europe/Berlin (36 h grace window) shrinks the underlying table by roughly 50× once it converges.

AI

  • IntakeHistoryListV2 on the medication detail page hides planned/scheduled rows by default; the API gains an explicit ?status=completed filter. Skipped rows render distinctly.

UX

  • HealthScoreCard fills the full Insights overview hero row height.
  • Sidebar + top-bar overflow menus keep menu items single-line at w-60.
  • Targets page card gap tightened to kill the dead band below each metric label.
  • Select chevron right-margin matches the date-picker icon gutter.
  • Mood mini chart byte-aligned with the BP and Weight minis.
  • Dashboard "Hinzufügen" button centre-aligns with the title on mobile.
  • Medication detail card symmetry — Mounjaro renders identically to Ramipril; GLP-1-specific data lives behind the header-actions kebab.
  • Coach disable cascade — when the global Coach flag is OFF, every Coach affordance disappears. Six in-band surfaces pinned by an invariant test; cross-cut gates carry sibling tests.
  • Settings → Export — Arztbericht hero card promotes the doctor report to a prominent CTA at the top of the page.
  • Dashboard quick-add — new Medikamenteneinnahme action opens a ResponsiveSheet with a smart medication picker (auto-selects the medication with an open dosing window).
  • Onboarding checklist toggle + dismiss button raised to the 44 px mobile touch floor (uncovered while wiring the e2e fix).
  • Timezone override toggle removed in favour of a silent browser-zone auto-seed.
  • Insights BMI status persists a sentinel cache row on the 20 s LLM timeout path so the spinner stops re-firing.

Security

  • New TRUST_CF_CONNECTING_IP env flag (default off) lets Cloudflare-fronted deployments read cf-connecting-ip for the rate-limit bucket and audit-log IP. .env.example documents the security implications: only set behind Cloudflare; nginx / Caddy / direct deployments must leave it off.
  • Hourly geo-backfill pg-boss job closes the gaps the v1.4.36 IP-whois UI fix surfaced.

Refactor

  • Shared window-status.ts + category-label.ts helpers collapse the previously duplicated medication-card logic.
  • CUMULATIVE_DAY_SUM_TYPES derives from CUMULATIVE_HK_TYPES so the cumulative-type registry is a single source of truth across the importer, drain, route, UI, and analytics metric-key mapping.
  • getClientIp and getClientIpOrTrustWarning share one ladder.

Validation

  • dayKey rejects impossible calendar values like 2026-02-30.
  • groupBy=day / dayKey requests with offset > 0 are rejected upfront.
  • Drill-down window honours DST transitions (Berlin Mar 30 + Oct 26 stop showing wrong hour-overlap counts).

CI

  • Vitest 4 timeout-option signature corrected on the 5 MB payload guard test.
  • Integration isolate:true for mock-state-sensitive notification dispatch tests.
  • e2e mobile-touch-target assertions updated to the 44 px floor.

Documentation

  • README rewrite with hero, status block, How-it-works walkthrough, and inline architecture diagrams.
  • healthlog-docs site refresh: three new integration mirrors, three placeholder pages filled, two new concepts pages.
  • healthlog-landing value-statement upgrade with two new sections.
  • Five new SVG diagrams in docs/diagrams/ (Dracula palette): data flow, Coach pipeline, self-hosting topology, source-priority ladder, security model.

Tests

  • Unit suite 4354 → 4486 passing. pnpm typecheck + pnpm lint clean. Integration suite stable at 230; the two pre-existing mock-isolation flakes (apns-dispatch / integration-status) stabilised by the isolate:true fix.

Operator notes

  • Coolify auto-deploys main on tag push. First webhook may pull a stale :latest; trigger a redeploy after the docker-publish workflow completes if so.
  • No new migrations. TRUST_CF_CONNECTING_IP is opt-in; existing deployments are unaffected unless they explicitly set it.

Deferred to v1.4.38

See CHANGELOG.md for the full backlog table (~50 items). Headline carry-overs: cross-tz fragility in the rollup fast-paths (must land before iOS user base broadens beyond Berlin), real pagination on the collapsed groupBy=day branch, per-process singleton-guard on the hourly geo-backfill for multi-worker deployments, and several smaller drift-risk cleanups identified by the code-review pass.

Don't miss a new HealthLog release

NewReleases is sending notifications on new releases.