Commit Graph
18 Commits
Author SHA1 Message Date
Marc-André Bombeck 497982b4b4 chore(release): v1.17.1 — preventive care, lab results, and more of the data you already have 2026-06-15 01:40:36 +02:00
Marc-André Bombeck 3f5b1a66a1 chore(release): v1.17.0 — clinical depth for glucose and sleep, three new sources
Add the blood-glucose clinical panel with Nightscout, sleep debt and chronotype,
Polar and Oura over OAuth, reorder-aware medication supply and an invite
deep-link. Every new metric is computed once on the server and read the same way
on the dashboard, the coach, the doctor-report and the companion app, each behind
a still-learning gate. The coach now reasons from the new signals, mood and cycle
entry is one sectioned sheet, and previously-hidden wearable data surfaces.
2026-06-14 21:29:45 +02:00
Marc-André Bombeck 870ee01826 chore(release): v1.16.17 — restore the sleep timeline, clear the dashboard after a dose
Two daily-use fixes: the last-night hypnogram bar collapsed to its breakdown
for nights whose stages share an end instant, and the dashboard kept prompting
for a dose until a full reload after it was recorded. No breaking changes.
2026-06-14 20:21:31 +02:00
Marc-André Bombeck 04b09e2905 chore(release): v1.16.16 — one engine for sleep, recovery and glucose
Read sleep, recovery and blood glucose from a single source on every surface —
dashboard, coach, doctor-report, CSV and FHIR exports, and the companion app —
so the displayed figure agrees wherever it appears. Sleep nights reconstruct
once with source de-duplication; WHOOP-native recovery is canonical and resolves
to one row per night; glucose converts to the user's unit at the point it is
served. Hardens the consent receipt path and deepens WHOOP sync with per-resource
cursors, targeted refresh and full backfill. Several displayed numbers become
correct-but-different — flagged in the changelog.
2026-06-14 17:58:56 +02:00
Marc-André Bombeck 8511b0bed7 chore(release): v1.16.15 — an honest calendar that learns before it predicts 2026-06-14 15:53:01 +02:00
Marc-André Bombeck ae1373637f chore(release): v1.16.14 — one number everywhere across score, coach, and doctor-report
Coherence release: blood-pressure in-target unified on a labeled, thin-data-gated
90-day window across tile, health-score pillar and coach; the dashboard ring and
insights card built from one shared health-score input builder; the coach and the
doctor-report PDF/FHIR adherence drawn from the same dose ledger as the detail page;
and a shared entry-timestamp plausibility guard on measurement and mood. Several
displayed figures become correct-but-different (BP headline window, adherence).
2026-06-14 14:02:45 +02:00
Marc-André Bombeck 5aefcd59eb chore(release): v1.16.13 — installable offline, era-correct dose edits, steadier headers
App-wide service-worker registration (installable + offline, authenticated
pages kept out of the cache, logout wipe), era-correct historical dose-edit
attribution, CSV intake stock consumption, WHOOP late-workout ingest, web AI
consent-receipt minting, the layout partial-PUT section merge, the curated
mood-tag catalog, and a sweep of mobile header fixes.
2026-06-14 11:06:10 +02:00
Marc-André Bombeck 3ad0649ff6 feat(pwa): add manifest shortcuts and a 192 maskable icon
Add three home-screen shortcuts (Add measurement, Today, Medications)
deep-linking into the app, each tagged `source=shortcut`. Add a 192×192
maskable icon alongside the existing 512 so adaptive launchers mask the
right size instead of downscaling the 512 or clipping the un-masked 192
"any" icon on circular masks.

No screenshots: the repo ships no real screenshot assets and fabricating
them is worse than the richer-install-dialog gain.
2026-06-14 10:49:00 +02:00
Marc-André Bombeck 60f587c5a7 fix(pwa): re-anchor the sw.js fallback version on every build
`public/sw.js` carries a `|| "..."` fallback literal used for `CACHE_VERSION`
when `importScripts('/sw-version.js')` is unavailable. The literal had drifted
to `v1.4.43`, four-plus minors behind `package.json`; in any environment where
the generated file is missing this keyed every cache to the stale version and
turned the activate-step eviction into a no-op — the exact bug the generator
was written to kill.

Extend the prebuild generator to rewrite the fallback literal in `sw.js` to the
current `package.json` version on every build, anchored on a
`/* @sw-version-fallback */` marker (the build fails loudly if the marker is
gone). The literal and the generated `sw-version.js` can no longer diverge.
The SW test now reads the fallback straight from the source so it tracks the
literal instead of hard-coding it.
2026-06-14 10:47:50 +02:00
Marc-André Bombeck 2a180fec95 fix(pwa): keep no-store and clinician-share pages out of the page cache
With the service worker now registered for every user, the network-first
page cache sees every authenticated navigation. The everyday app routes
are client-fetch-only shells with no server-rendered PII, but the
`/c/[token]` clinician-share view renders health values straight into the
HTML and emits `no-store`. The page cache ignored the header and stored
it, so a revoked or expired share could still render back offline.

Gate `cache.put` in `networkFirst` on a new `isCacheableNavigation`
check: skip any response carrying `Cache-Control: no-store` (the
principled rule for any present or future server RSC that renders user
data) and skip the `/c/*` path outright as belt-and-braces. Ordinary
navigations still cache unchanged.
2026-06-14 10:45:39 +02:00
Marc-André Bombeck 6f45d72a84 fix(ui): unclip the score-ring glow, reachable insight pills, consistent destructive actions
The score ring's bloom was clipped by the SVG's own viewport — the
drop-shadow sits on a child of the viewBox-filling arc — so the glow
never extended past the circle; the SVG now overflows visibly on every
host. The insight pill strip gains chevron buttons and wheel scrolling
so an overflowing row is reachable with a mouse. Safari favourites
rendered the transparent icon on a white plate; a flattened
apple-touch-icon and a maskable manifest icon fix both. The
time-of-day mood chart adopts the damped fill the weekday chart already
uses, eighteen delete confirmations move onto the destructive button
variant (one of them had the wrong text colour), five confirmation
dialogs gain pending states, the sources dialog stacks its primary
action on top on mobile, and the token form aligns input and button
heights.
2026-06-10 12:56:06 +02:00
Marc-André Bombeck 298e4c34b4 perf: collapse the medication compliance hot path and the dashboard fan-out
The medication list fired one compliance request per card every 30
seconds, and each request scanned the medication's full intake history
and expanded the recurrence calendar five to six times. The endpoint now
mints bands once per request, serves the sub-windows from that single
ledger, bounds the event read to a year of selected columns and sits
behind a write-invalidated 15-minute server cache; the cards poll at
five minutes. The dashboard drops two redundant checklist queries by
reading counts from the snapshot, the BMI chart derives from the weight
series instead of refetching it, the detail page no longer serialises
behind the auth probe and seeds its query from the list row. Expensive
analytics reads gain a shared per-user rate limit, and the service
worker stops serving cross-version shells, enables navigation preload
and trims caches in one pass.
2026-06-10 12:55:56 +02:00
Marc-André Bombeck 33ca595405 feat(medications): replace the injection-site body map with a refined illustration
Swap the hand-authored body silhouette in the injection-site picker for a
clean, gender-neutral medical line-art figure with correct proportions
(arms to mid-thigh, head-to-body ≈1:7.5, separated legs, feet). The figure
ships as a small transparent raster (~8 KB) and is painted theme-aware: its
alpha drives an SVG mask over a currentColor rect, so the strokes take the
picker's text colour and tint correctly in light and dark.

Keeping the figure inside the SVG (rather than a CSS-masked sibling) means
it shares the dots' 100×200 viewBox, so alignment stays responsive by
construction. Recalibrate SITE_COORDS so the upper-arm, abdomen-quadrant
and thigh anchors land on the new figure's anatomy; the pointer overlay,
keyboard targets, recommendation ring, last-used marker and disabled-set
logic are unchanged.
2026-06-04 21:34:10 +02:00
Marc-André Bombeck 6c7fc7dc84 chore(release): v1.4.45 — analytics 9 s perf fix + audit-marathon closure + v1.4.44 hotfix merged
Audit-marathon close: 14 waves + W10 QA + reconcile. Perf fix (analytics 9 s -> 2-3 s), Zod multi-issue rollout (41 routes), Withings parked-state automation, mobile-UI WCAG 2.5.5 close, QoL i18n + offline banner + account delete, security PII drop + replay-injection scan. Migration 0075 required. Tests 4815 -> 5076.
2026-05-21 23:13:21 +02:00
Marc-André Bombeck 34a8f081ef feat(app): self-heal the stale-shell post-deploy paper-cut
The v1.4.38.3 `AppError` boundary reloads once when a stale shell
trips `ChunkLoadError`, but the reload only fires AFTER the user
hits a navigation that lazy-loads a missing chunk. Users sitting on
the dashboard or insights overview ride out the staleness until
their next click; some never click and the cached shell silently
drifts further out of date with every deploy.

Three layered fixes so the running app heals itself instead:

- `public/sw.js` now keys both `STATIC_CACHE` and `PAGE_CACHE` to
  the app release tag (`v1.4.38.4`). The `activate` step already
  evicts any cache name outside the current pair, so bumping the
  string at release time guarantees the precached root HTML and the
  precached `/_next/static/*` chunks from the previous deploy are
  dropped on the next SW install.
- `next.config.ts` injects `NEXT_PUBLIC_APP_VERSION` from
  `package.json` into the client bundle so the running shell knows
  which release it was built against.
- New `<VersionPoller>` client component mounts inside `<Providers>`
  and polls `/api/version` every 60 s. If the live version moves
  ahead of the shell-baked version it unregisters every active SW,
  wipes CacheStorage, and `window.location.reload()`s.
  `sessionStorage` gates the reload to once per session so a
  mid-deploy webhook race that briefly returns a stale image cannot
  loop the page.
2026-05-18 05:49:24 +02:00
Marc-André Bombeck f5962497d6 v1.4.34.4 — audit-driven hotfix bundle (security, UX, code-quality, docs)
Consolidated hotfix landing the findings from a six-axis audit
covering mobile security, UX + accessibility, code quality + docs,
README + discoverability, web performance, and mobile-deep responsive
behaviour. None of the changes break the public API or the existing
data shape; every fix is additive and SAFE under the v1.4.34.x web
freeze. Full audit reports live in `.planning/round-audit-*.md`.

Security
  - Password rotation now wipes API tokens + refresh tokens in the
    same `$transaction` as session revocation. A stolen iOS Bearer no
    longer survives a user-initiated password change or an admin reset.
  - `/.well-known/` proxy bypass tightened to an explicit-allowlist
    `Set`. Stale `/api/auth/codex/callback` PUBLIC_PATHS entry dropped.
  - HSTS gains `preload`. Withings host removed from the global CSP
    and gated to the integration's own routes.
  - `getClientIp` warns once per process on `TRUST_PROXY_HOPS`/XFF
    mismatch + exposes a tagged helper for tighter universal buckets.
  - Service worker rejects off-origin notification-click URLs. Offline
    fallback body switched to a locale-neutral icon. Manifest gains
    `scope`, `id`, `display_override`.

UX + accessibility
  - i18n leaks closed on Dialog/Sheet close-X, ChartSkeleton's loading
    announcement, and the notifications-section breadcrumb.
  - Focus rings on bottom-nav, the More overflow button, and the
    mobile top-bar user menu.
  - Tap-target floor: Input / NativeSelect / Select / DateTimeInput
    switch to `h-11 sm:h-10`.
  - Admin chip-strip auto-scroll-into-view (matches v1.4.33 settings).
  - List-page subtitles visible on mobile.
  - Insights empty-state CTA vocabulary normalised so the link opens
    the right measurement form (was silently failing for
    BODY_TEMPERATURE / BLOOD_GLUCOSE / PULSE).

Mobile-deep
  - `viewport.themeColor` reacts to light/dark mode.
  - TopBar + Coach FAB reserve safe-area-inset-top / -bottom for
    notched iPhones.
  - Sonner toaster switches to `theme="system"`.

Code quality
  - `SESSION_SECRET` dropped — the env var was documented as required
    but never read by code. Three secrets, not four. Self-hosters
    upgrading can delete the existing line.
  - `toJson<T>()` helper consolidates seven Prisma JSON-cast sites.
  - `db-compat.ts` gains a header docstring naming it the
    schema-bootstrap path.
  - Passkey response types adopted from `@simplewebauthn/server`;
    `any` + eslint-disable pragmas drop out.
  - Zero-TODO CI gate added at `.github/workflows/no-todo-markers.yml`.

Documentation + discoverability
  - README rework: How-it-compares matrix, Apple Health + AI Coach
    promoted to standalone Key-Features bullets, status block, latest
    release + GHCR badges, OpenAPI pointer, three-secret Quick Start.
  - openGraph + twitter cards now carry `images` and a
    `summary_large_image` Twitter card.
  - GitHub repo metadata: description tightened from 290 to 156
    chars + keyword-front, `homepageUrl` flipped from a personal
    tenant to the demo site, six generic / PII-adjacent topics
    swapped for six high-intent ones.
  - Five new user-facing docs: `docs/self-hosting/getting-started.md`,
    `docs/self-hosting/reverse-proxy.md`,
    `docs/integrations/apple-health.md`,
    `docs/integrations/withings.md`,
    `docs/integrations/ai-providers.md`.
  - `docs/README.md` clarifies the docs tree as internal playbooks
    vs the user-facing `docs.healthlog.dev` site.
2026-05-17 00:39:58 +02:00
Marc-André BombeckandClaude Opus 4.7 02b99553b9 chore(style): repo-wide prettier sweep before v1.4.6 tag
Long-overdue prettier sweep; prettier had drifted vs. checked-in code
across ~130 files (mostly long-argument line-break wrapping in TS and
table-padding in markdown). Pure formatting — no semantic changes —
and required to clear the v1.4.6 release gate's `pnpm format:check`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 02:27:17 +02:00
Marc-André Bombeck 38309932f3 Initial release v1.0.0
HealthLog — personal health-tracking PWA with weight, blood pressure,
pulse, mood tracking, medication compliance, Withings integration,
doctor report PDF export, and Dracula-themed UI.
2026-03-10 20:14:33 +01:00