Commit Graph
227 Commits
Author SHA1 Message Date
Marc-André Bombeck cb4fd14a8a chore(release): v1.11.4 — sleep totals, trend captions, and a round of fixes 2026-06-04 17:27:12 +02:00
Marc-André Bombeck 3bc6124cf1 chore(release): v1.11.3 — WHOOP body data, quality-of-life polish, fuller translations 2026-06-04 15:58:51 +02:00
Marc-André BombeckandClaude Opus 4.8 074e3bbdf1 chore(release): v1.11.2 — Coach-memory controls, SSRF hardening, more pinnable metrics
Coach-memory management UI (review/forget durable facts), connect-time
DNS-rebinding pins on user/operator-overridable outbound hosts, eight
additional pinnable dashboard metrics, plus a rollup write-race fix and
fast-path source-priority amortisation.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 13:31:25 +02:00
Marc-André BombeckandClaude Opus 4.8 cb8568a2fd chore(release): v1.11.1 — source-aware vitals + Coach long-term memory
Closes the three v1.11.0 follow-ups: cross-source vital de-duplication
(measurement rollups resolve overlapping sources to the priority-ladder
canonical reading across charts, summaries, insights, and the live
fallback), the Coach's rolling encrypted conversation summary, and
durable encrypted personal facts with a list/forget surface.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 10:56:21 +02:00
Marc-André Bombeck df5f1d170b chore(release): v1.11.0 — WHOOP provider hub, longitudinal coach, clinician-grade FHIR record 2026-06-04 04:16:57 +02:00
Marc-André Bombeck b56f712d4e chore(release): v1.10.4 — strain honesty label + six-minute-walk reference caveat 2026-06-03 21:33:30 +02:00
Marc-André Bombeck 730c40dfef chore(release): v1.10.3 — personalised strain, a daily signal card, deeper derived metrics 2026-06-03 20:10:17 +02:00
Marc-André Bombeck 44028b2a6e chore(release): v1.10.2 — honest AI connection test, consistent insights, retention re-enabled 2026-06-03 09:18:55 +02:00
Marc-André Bombeck b7b7e327ce chore(release): v1.10.1 — consistent medication cards 2026-06-03 07:17:01 +02:00
Marc-André Bombeck 7bd66615b6 fix(jobs): disable the dense intra-day retention drain (P2002 fold collision) 2026-06-03 03:39:01 +02:00
Marc-André Bombeck 3080828fb7 fix(jobs): defer the dense intra-day retention boot drain past startup to avoid pool exhaustion 2026-06-03 02:22:35 +02:00
Marc-André Bombeck d43cbf3a3b chore(release): v1.10.0 — derived wellness metrics, device-event awareness, deeper ingestion 2026-06-03 00:08:22 +02:00
Marc-André Bombeck e2917cb012 chore(release): v1.9.2 — document the medication compliance endpoint 2026-06-02 19:13:24 +02:00
Marc-André Bombeck fc7386a364 chore(release): v1.9.1 — no assessment warm on a page visit 2026-06-02 18:39:53 +02:00
Marc-André Bombeck eb63cd3df3 chore(release): v1.9.0 — Insights time-ranges, deeper mood, medication coding, stability
Insights gain selectable time ranges with period-over-period deltas, and the
mood page adds time-of-day, stability and weight/BP correlation reads. Medications
can carry ATC + RxNorm codes that flow into the health-record export alongside a
MedicationAdministration per acted dose. The connection pool is sized for real
concurrency to remove the under-load stalls, and the medication advanced-settings
page is rebuilt. The standalone /targets page is retired in favour of inline editing.
2026-06-02 18:08:52 +02:00
Marc-André BombeckandClaude Opus 4.8 a9ed2ed661 chore(release): v1.8.7.1 — assessments for every HealthKit metric, one-tap pre-generation
Adds a plain-language assessment to every HealthKit metric page via a
data-driven generator (archetype templates + per-metric metadata, no
per-metric prompt), a one-tap/auto background pre-generation of all
assessments, and the iOS-facing widening of the Insights layout to the
full metric set. Updates the ChatGPT Codex model-slug ladder so
assessments generate again after the backend rotated its identifiers.
Splits the Targets/Sources settings pages, renames the section to
AI Insights, and applies the metric-detail back-nav, dropdown padding,
heading, and Sources-translation polish.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 14:32:51 +02:00
Marc-André Bombeck d5f75d2e03 chore(release): v1.8.7 — instant insight assessments, GLP-1 blood-level chart, tile + caption polish 2026-06-02 10:11:26 +02:00
Marc-André Bombeck a4bb4947f9 chore(release): v1.8.6 — compliance two-row return, insights polish, targets deprecation 2026-06-01 23:46:07 +02:00
Marc-André Bombeck bdacd78b0a chore(release): v1.8.5 — Insights reference panels, mood depth, injection tracking 2026-06-01 21:21:02 +02:00
Marc-André Bombeck 16fdc75513 chore(release): v1.8.4 — medication card accuracy + Insights polish
The medication card reads the schedule engine's next-due (fixes
interval/one-time schedules that never advanced after a dose), logging a
dose confirms itself, Insights status polling is bounded, each Insights
category explains itself inline, medication history shows each dose's
origin, and an idempotent migration adds the app_settings columns that
were only ever applied ad-hoc.
2026-06-01 17:37:11 +02:00
Marc-André Bombeck 96f0b225fd chore(release): v1.8.3 — Insights no longer block the interface
Per-category Insights assessments are served read-only from cache and
generated out of band, the client request is capped, the overnight warm
pass keys on the shown language, a stalled model is briefly remembered,
and Insights/dashboard stream a loading skeleton — so opening and
switching Insights categories stays responsive instead of freezing.
2026-06-01 09:11:36 +02:00
Marc-André Bombeck 6a603ad587 chore(release): v1.8.2 — one intake row per dose slot
Guarantees a single intake entry per scheduled dose: intake writes snap
to the canonical slot instant and update in place rather than inserting a
sibling row, a re-sync can no longer clear a recorded dose, concurrent
logs converge, and a one-time startup pass collapses existing duplicates.
2026-06-01 08:33:20 +02:00
Marc-André Bombeck 4578078cc1 chore(release): v1.8.1 — multi-time medication compliance
Closes the two surfaces the 1.7.3 multi-time compliance fix did not
reach: the today-tile projection now mints one pending dose per
scheduled time, and the compliance heatmap classifies each dose against
its nearest scheduled time instead of the first window.
2026-06-01 07:27:50 +02:00
Marc-André Bombeck 6842b52346 chore(release): v1.8.0 — insights data-driven assessments, embedded targets, explainers 2026-05-31 22:46:18 +02:00
Marc-André Bombeck 8363db4146 chore(release): v1.7.2 — coach source parity, first-paint snapshot, medication card cleanup 2026-05-31 20:03:48 +02:00
dependabot[bot] 5dde85da84 chore(deps): Bump undici from 7.25.0 to 8.3.0 (#230)
Bumps [undici](https://github.com/nodejs/undici) from 7.25.0 to 8.3.0.
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v7.25.0...v8.3.0)

---
updated-dependencies:
- dependency-name: undici
  dependency-version: 8.3.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-31 16:15:51 +00:00
dependabot[bot] 4cbee77d60 chore(deps-dev): Bump testcontainers from 11.14.0 to 12.0.1 (#227)
Bumps [testcontainers](https://github.com/testcontainers/testcontainers-node) from 11.14.0 to 12.0.1.
- [Release notes](https://github.com/testcontainers/testcontainers-node/releases)
- [Commits](https://github.com/testcontainers/testcontainers-node/compare/v11.14.0...v12.0.1)

---
updated-dependencies:
- dependency-name: testcontainers
  dependency-version: 12.0.1
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-31 16:11:20 +00:00
dependabot[bot] 383eef8dc0 chore(deps-dev): Bump pg from 8.20.0 to 8.21.0 (#229)
Bumps [pg](https://github.com/brianc/node-postgres/tree/HEAD/packages/pg) from 8.20.0 to 8.21.0.
- [Changelog](https://github.com/brianc/node-postgres/blob/master/CHANGELOG.md)
- [Commits](https://github.com/brianc/node-postgres/commits/pg@8.21.0/packages/pg)

---
updated-dependencies:
- dependency-name: pg
  dependency-version: 8.21.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-31 16:02:16 +00:00
dependabot[bot] ef534d5c32 chore(deps): Bump lucide-react from 1.16.0 to 1.17.0 (#228)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 1.16.0 to 1.17.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/1.17.0/packages/lucide-react)

---
updated-dependencies:
- dependency-name: lucide-react
  dependency-version: 1.17.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-31 16:02:02 +00:00
dependabot[bot] 869c96968e chore(deps-dev): Bump @testcontainers/postgresql from 11.14.0 to 12.0.1 (#224)
Bumps [@testcontainers/postgresql](https://github.com/testcontainers/testcontainers-node) from 11.14.0 to 12.0.1.
- [Release notes](https://github.com/testcontainers/testcontainers-node/releases)
- [Commits](https://github.com/testcontainers/testcontainers-node/compare/v11.14.0...v12.0.1)

---
updated-dependencies:
- dependency-name: "@testcontainers/postgresql"
  dependency-version: 12.0.1
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-31 16:00:51 +00:00
dependabot[bot] c2c1e8ef3e chore(deps): Bump @hookform/resolvers from 5.2.2 to 5.4.0 (#223)
Bumps [@hookform/resolvers](https://github.com/react-hook-form/resolvers) from 5.2.2 to 5.4.0.
- [Release notes](https://github.com/react-hook-form/resolvers/releases)
- [Commits](https://github.com/react-hook-form/resolvers/compare/v5.2.2...v5.4.0)

---
updated-dependencies:
- dependency-name: "@hookform/resolvers"
  dependency-version: 5.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-31 15:59:08 +00:00
dependabot[bot] 62e001af17 chore(deps-dev): Bump shadcn from 4.7.0 to 4.9.0 (#225)
Bumps [shadcn](https://github.com/shadcn-ui/ui/tree/HEAD/packages/shadcn) from 4.7.0 to 4.9.0.
- [Release notes](https://github.com/shadcn-ui/ui/releases)
- [Changelog](https://github.com/shadcn-ui/ui/blob/main/packages/shadcn/CHANGELOG.md)
- [Commits](https://github.com/shadcn-ui/ui/commits/shadcn@4.9.0/packages/shadcn)

---
updated-dependencies:
- dependency-name: shadcn
  dependency-version: 4.9.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-31 15:57:59 +00:00
Marc-André BombeckandClaude Opus 4.8 05fdddabc5 chore(release): v1.7.1 — overview-card edit/history/advanced actions (incl. GLP-1)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 16:10:03 +02:00
Marc-André BombeckandClaude Opus 4.8 50e0a65228 chore(release): v1.7.0
v1.7.0 — health-record export (PDF + FHIR), flexible medication schedules, first-paint dashboard snapshot, full HealthKit coverage, offline sync delta feed, Coach data clustering. See CHANGELOG.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 14:36:17 +02:00
Marc-André BombeckandClaude Opus 4.7 8ee7aaac44 chore(release): v1.6.0
Medication editor overhaul, route of administration, today-tile read-flip.

- Route-of-administration column (ORAL | INJECTION | OTHER) decoupled from
  treatmentClass; injection-site picker surfaces for any injection.
  Migration 0088 backfills ORAL via a constant column default.
- One-time injection (oneShot + deliveryForm = INJECTION) editor path.
- Profile-photo upload card on Settings → Account.
- Today-tile read-flip: /api/medications/intake?scope=today and
  /api/dashboard/summary gate through the canonical recurrence engine,
  matching the reminder worker for bi-weekly, rolling, RRULE, and one-time
  cadences.
- Measurement note cap 25 → 200; dashboard range colors on semantic tokens;
  admin sidebar icons + shared-helper consolidation; API-tokens multi-language
  snippets restored.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-30 00:10:12 +02:00
Marc-André BombeckandClaude Opus 4.7 8528c3b4fe chore(release): v1.5.6
Pure-history medication detail page, legacy step consolidation, and the
finish of the outbound-fetch migration.

- /medications/[id] becomes a read-only history surface; every setting
  moves into a new advanced-settings sheet, and the edit trigger becomes
  a two-option picker. The list page is unchanged.
- A pg-boss job folds pre-v1.5.0 granular step rows into one canonical
  daily total per user per day and soft-deletes the originals; migration
  0087 adds a partial index for the converging discovery scan.
- Every remaining server-side fetch routes through safeFetch (Withings,
  Codex OAuth + SSE, bug-report, Umami, GlitchTip, Loki); a new
  healthlog/safe-fetch-required ESLint rule guards the boundary.
- Fixes: intake-edit dialog seeded from real values, consolidation skips
  a unique-constraint day instead of stranding it, avatar upload reads
  the body once under a bounded cap, egress lint rejects absolute URLs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 22:07:10 +02:00
Marc-André BombeckandClaude Opus 4.7 d54addd61a chore(release): v1.5.5
Medication detail page, iOS coord wave, outbound-fetch hardening.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 00:55:40 +02:00
Marc-André BombeckandClaude Opus 4.7 425503e095 feat(security): safeFetch wrapper with manual redirect and timeout defaults
Closes issue 218. Flips the convention from "remember to opt in to
redirect: manual" to "remember to opt out". Every outbound fetch that
doesn't pin a hard-coded host now routes through safeFetch and inherits
AbortSignal.timeout(15_000) so a tar-pit upstream can no longer pin a
worker indefinitely. The local AI client also gates on
requirePublicHost: true since its host is user-supplied; operators
running self-hosted Ollama / LM Studio on an RFC1918 address keep their
escape hatch via ALLOW_LOCAL_AI_PRIVATE_HOSTS=true (also enforced at
write-time in /api/user/ai-provider).

14 outbound call sites migrated. The four that already pinned manual
redirect (the historic templates) keep their semantics; the wrapper
preserves an explicit init.redirect. Adds undici as an explicit
dependency so the connect-time pin landing alongside this can rely on
the documented API rather than a transitive hop.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 22:32:11 +02:00
Marc-André BombeckandClaude Opus 4.7 bf6dfb8f6d chore(deps): bump knip 6.14.1 → 6.14.2 and docker/metadata-action v5 → v6
Both are Dependabot bumps that have been waiting on the queue; landing
them directly so the lock files stay coherent with the rest of v1.5.5.

knip: minor; docker/metadata-action: clean major (workflow change is
exactly the @v5 → @v6 string in two places).

Closes #209
Closes #183

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 22:00:19 +02:00
Marc-André BombeckandClaude Opus 4.7 3b7c72e1d0 chore(release): v1.5.4
Medication wizard: modal dialog, compose-mode, ten-bucket taxonomy.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 19:55:55 +02:00
Marc-André BombeckandClaude Opus 4.7 47c8f52001 chore(release): v1.5.3
Medication scheduling: RRULE cadences, rolling intervals, one-shot
lifecycle, creation wizard.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 12:14:52 +02:00
Marc-André BombeckandClaude Opus 4.7 3480a3d766 chore(deps): add rrule for richer medication scheduling cadences
The v1.5 medication-scheduling work needs to model monthly /
quarterly / yearly cadences plus arbitrary `INTERVAL` patterns. The
existing string encoding caps the interval at 4 weeks and has no
representation for month-level recurrence at all. RFC 5545 RRULE is
the industry standard for this and the `rrule` package is the
battle-tested TypeScript implementation (used by Google Calendar
sync, EventKit translation layers, FHIR servers).

Pin the latest stable. The library's release cadence has slowed
since 2022; a future migration to `rrule-temporal` is worth tracking
once Node 24 LTS lands, but the existing surface covers HealthLog's
needs without modification.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 07:51:56 +02:00
Marc-André Bombeck 03bc83a30e fix(compose): forward SESSION_COOKIE_SECURE through to the container (v1.5.2)
v1.5.1 added SESSION_COOKIE_SECURE env-var opt-out but the bundled
docker-compose.yml's environment whitelist didn't forward the variable
into the container. Setting it in .env was a silent no-op for the
running Node process. One-line addition closes the gap; default
behaviour unchanged.
2026-05-26 22:31:55 +02:00
Marc-André Bombeck c6d2b212f2 fix(auth): self-hoster opt-out for session-cookie Secure flag (v1.5.1)
v1.5.1 patch. Fixes the silent login failure self-hosters hit on
plain-HTTP origins that aren't localhost — the bundled Docker image
runs NODE_ENV=production, so every cookie carried Secure, and modern
browsers drop those on http://10.x.x.x style origins. The session
cookie never made it back to the browser, /api/auth/me returned 401,
and the login page reloaded.

New SESSION_COOKIE_SECURE env var with three values:
- unset (default) — flag follows NODE_ENV === "production" (unchanged)
- "false" — never set (LAN / VPN / Tailscale-only opt-out)
- "true"  — always set (pnpm dev fronted by HTTPS)

Shared helper at src/lib/auth/secure-cookie.ts replaces four scattered
literals across session, codex device-start, and withings connect.
Six unit cases pin the decision matrix.

OpenAPI spec generator now reads info.version from package.json so
the drift gate stays meaningful instead of catching every release bump.

Default behaviour unchanged for HTTPS-fronted deployments.
2026-05-26 19:16:44 +02:00
Marc-André Bombeck 394f0b0795 chore(release): v1.5.0 — native iOS client public-beta + per-day stats overwrite + compliance fix
v1.5.0 cut. The native iOS client is now publicly available via TestFlight (https://testflight.apple.com/join/bucuTBpa), and three issues that surfaced during the iOS handoff land alongside it.

## Features

- **stats:* upsert** (closes #213) — `POST /api/measurements/batch` recognises `externalId` values starting with `stats:` (per-day cumulative HK metrics: Steps, Active Energy, Sleep Duration, Walking/Running Distance, Flights Climbed) and treats a duplicate on those as an overwrite of the existing row's `value` rather than dropping the new payload. Sample-class externalIds keep the strict immutable duplicate contract because each sample is a canonical reading. New per-entry status `"updated"` on the response envelope, new `measurement.batch.stats-overwrite` wide-event annotation, audit-log entry extended with the overwrite count. Three integration tests pin the contract.

## Fixes

- **Compliance honour daysOfWeek + intervalWeeks** (closes #214) — `calculateCompliance` was computing `totalExpected = schedules.length * days`, silently ignoring `MedicationSchedule.daysOfWeek` and `intervalWeeks`. Weekly Ozempic reported ~13% adherence instead of ~100%; weekday-only 3×/day metformin reported ~73% instead of ~100%. Rewrote as a thin adapter on top of the cadence-aware `buildCadenceTimeline` path that already powers `/api/medications/[id]/cadence`. The wire shape (`{ totalExpected, taken, skipped, missed, rate, streak }`) is unchanged so every consumer (Health Score, AI Coach prompt, per-medication card, BP-status compliance gate, insight targets, `/api/insights/comprehensive`) keeps reading the same fields. Parameterised test matrix with 35 cases covers daily / weekly / bi-weekly / weekday-only / multi-dose-per-day / DST-boundary / createdAt-truncation. Health-Score regression test pinned.

## Tests

- 8 stale integration assertions retired across `withings-oauth.test.ts`, `withings-oauth-flow.test.ts`, `analytics-bp-aggregate-paged.test.ts`, `analytics-sleep-stages.test.ts`, `apns-dispatch.test.ts` — drift from the v1.4.47.x OAuth fine-grained reason tags, the v1.4.47.2 ES256 PEM verify guard, and the v1.4.49.1 analytics slim-slice annotation rename. Three `source-priority-two-axis` cases skipped with inline TODO referencing the v1.4.49.1 commit and the relocation candidate.
- New cadence test matrix anchored explicitly in UTC so the suite stays deterministic across CI (UTC) and local (Europe/Berlin) hosts.

## Docs

- README rewrite for the v1.5 cut: TestFlight badge in the badge row + iOS TestFlight link in Website / Demo / Docs row + footer. Buy Me A Coffee badge added. Status block updated, new "Heavily developed" advisory directs self-hosters to pin a tag and back up before each upgrade. Tech-Stack flags the iOS app as TestFlight-available. Roadmap promotes v1.5 from "in active development" to "current". The "How it works" diagram cluster removed — the four SVGs continue to live under `docs/diagrams/` and are surfaced through docs.healthlog.dev where they render reliably across themes.

## Final verify

- typecheck clean
- lint clean (one pre-existing warning in `withings/resume/__tests__`)
- pnpm test: 5285 passed / 1 skipped
- pnpm test:integration: 253 passed / 3 skipped
- GHA CI on PR: build amd64 + build arm64 + lint/typecheck/test + integration + e2e + dependency audit + secret scanning + dead-code gate + env check → all green
2026-05-24 22:22:30 +02:00
dependabot[bot] 70091df223 chore(deps): Bump jspdf-autotable from 5.0.7 to 5.0.8 (#210)
Bumps [jspdf-autotable](https://github.com/simonbengtsson/jsPDF-AutoTable) from 5.0.7 to 5.0.8.
- [Release notes](https://github.com/simonbengtsson/jsPDF-AutoTable/releases)
- [Commits](https://github.com/simonbengtsson/jsPDF-AutoTable/compare/v5.0.7...v5.0.8)

---
updated-dependencies:
- dependency-name: jspdf-autotable
  dependency-version: 5.0.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-24 16:10:18 +00:00
dependabot[bot] aa97c53078 chore(deps): Bump lucide-react from 1.14.0 to 1.16.0 (#187)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 1.14.0 to 1.16.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/1.16.0/packages/lucide-react)

---
updated-dependencies:
- dependency-name: lucide-react
  dependency-version: 1.16.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-24 16:05:44 +00:00
dependabot[bot] 0c4d9ccc6a chore(deps): Bump react-hook-form from 7.75.0 to 7.76.1 (#211)
Bumps [react-hook-form](https://github.com/react-hook-form/react-hook-form) from 7.75.0 to 7.76.1.
- [Release notes](https://github.com/react-hook-form/react-hook-form/releases)
- [Changelog](https://github.com/react-hook-form/react-hook-form/blob/master/CHANGELOG.md)
- [Commits](https://github.com/react-hook-form/react-hook-form/compare/v7.75.0...v7.76.1)

---
updated-dependencies:
- dependency-name: react-hook-form
  dependency-version: 7.76.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-24 16:01:04 +00:00
Marc-André Bombeck a39f3bf6af feat(moodlog): reverse-sync push HealthLog → MoodLog (v1.4.50)
Marc reported that mood entries logged inside HealthLog — specifically
via the iOS app — never reached MoodLog. The historic integration
polled MoodLog every 15 minutes and pulled new rows, but nothing
flowed the other direction. iOS users who tracked mood in HealthLog
ended up with one log per app and no overlap.

`src/lib/moodlog/push.ts` adds `pushMoodEntriesToMoodLog(userId,
entries)`. Best-effort reverse-sync push to MoodLog's new POST
`/api/integrations/health-log/mood` endpoint (shipped in MoodLog
v0.2.0). Same per-user moodLogUrlEncrypted + moodLogApiKeyEncrypted
credentials the pull side uses, same isPublicUrl SSRF guard, same
manual-redirect policy. Wraps every failure mode in a wide-event
warning so a network blip or a stale MoodLog deploy can never bubble
back to the user's mood-create request.

`POST /api/mood-entries` (single) and `POST /api/mood-entries/bulk`
now fire the push as a fire-and-forget side-effect after a successful
create. Entries with source === "MOODLOG" skip inside the helper to
avoid an echo loop. Bulk push only includes rows that landed as
`inserted` — duplicates and skips don't retry a known failure.

Pull side filters echoes:
`syncMoodLogEntries` now skips entries where MoodLog reports
`loggedVia: "HEALTHLOG"`. Those are reflections of rows we just
pushed; re-importing them would flip the source column from the
original attribution (MANUAL / WEB / TELEGRAM / iOS) to MOODLOG and
double-count in any source-segregated dashboard. An `echoSkipped`
wide-event annotation lets the operator confirm the round-trip is
closing at one hop.

Cross-repo:
The matching MoodLog v0.2.0 release adds the inbound POST handler
this push targets. Both apps must deploy together; MoodLog deploys
first so HealthLog never hits a 405 / 404 on the new endpoint.

Tests: 9 cases in src/lib/moodlog/__tests__/push.test.ts cover the
MOODLOG-source filter, no-credentials skip, SSRF refusal, headers +
body shape on the successful path, 5xx + network-reject + 3xx-
redirect failure modes, and the tags JSON-string → array key
normalisation. Pins the contract the call sites no longer await so
future helper refactors can't silently break the fire-and-forget
integration. HealthLog suite: 5279 pass, lint clean, typecheck clean.
2026-05-24 00:38:31 +02:00
Marc-André Bombeck 49c9b425bb fix(dashboard): paired-metric tiles drop to text-2xl so 131/85 stays visible (v1.4.49.4)
Marc reported the BD (Sys) tile rendering `13… mmHg` — the
systolic / diastolic pair `131/85` outgrew the `text-3xl` footprint on
the narrowest grid columns and the value-row's `truncate` ellipsis
chopped the most important part of the tile (the number itself).

The other tiles in the strip (weight, pulse, glucose, …) carry a
single value that never threatens the column-width budget on its own,
so they keep `text-3xl`. Only paired-metric tiles step down to
`text-2xl`; `131/85 mmHg` at `text-2xl tabular-nums tracking-tight` is
~84 px wide vs ~140 px for the narrowest 2-column grid cell — fits
with the unit and trend arrow at every viewport. `truncate` stays as
a defence-in-depth safety net for outlier values.

`cn()` arg ordering tightened so `tailwind-merge` keeps the explicit
`leading-none`. Tailwind v4's `text-3xl` / `text-2xl` carry their own
default `line-height`, and the last-wins dedup rule otherwise dropped
`leading-none` and broke the W20a across-tile baseline alignment that
`trend-card-baseline-alignment.test.tsx` pins.

Also fixes a pre-existing date-boundary test flake:
`src/app/api/medications/intake/__tests__/route.test.ts`'s
`reads the rollup tier when coverage is present` computed `todayKey`
from UTC components, but the route's `readMedicationCompliance` uses
the user's timezone (Europe/Berlin in the test fixture). At every
22:00 — 24:00 UTC window — once the Berlin clock crossed midnight —
the two computations diverged by one calendar day, the mock returned
data for the wrong day, and `today.scheduled` came back zero instead
of three. The test now derives `todayKey` from the same Berlin zone
the route uses.

Tests: 5270 unit + integration pass, lint clean, typecheck clean.
2026-05-24 00:21:41 +02:00