chore(release): v1.4.16

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Marc-André BombeckandClaude Opus 4.7 committed 2026-05-10 03:39:53 +02:00
1 parent 5e893822db
commit d443c22d4e
2 files changed
+170 -1

No files matched your search

+169
View File
@@ -1,5 +1,174 @@
# Changelog
## [1.4.16] — 2026-05-09
### Added
- **Per-recommendation explainability.** Every insight recommendation now
carries a rationale: which time window was analysed, what was compared,
and the deviation that triggered the recommendation. The card expands
inline to reveal the rationale plus a mini-chart of the data window.
- **Confidence score per recommendation.** Each recommendation gets a
deterministic 0–100 confidence score (server-computed from sample size,
recency, and signal strength) shown as a colour-banded ring + bar meter.
Below-threshold recommendations are tagged "low confidence — based on
limited data" rather than hidden.
- **"Was this helpful?" feedback.** Thumbs-up / thumbs-down on every
recommendation, persisted per user with provider attribution. Daily
aggregator writes per-(severity × provider) helpful-rate to admin
settings; the aggregate is visible under `/admin/ai-quality`.
- **Medical-reference grounding.** Recommendations cite curated AHA / ESH
/ ESC / WHO / DGE guidelines via a validated `referenceId`; the
citation links open the source guideline in a new tab.
- **Multi-provider AI fallback chain.** The insight wrapper tries each
configured provider in turn on hard failures (401 / 403 / 429 / 5xx /
transport). Schema 422 still bubbles. Last-working provider is cached
per user for an hour. Order, enable / disable, and provider list are
configurable under Settings → AI.
- **Apple-Health-style chart polish.** Blood pressure, weight, pulse,
body fat, sleep, steps, mood, and medication-compliance charts gain
gradient fills, smooth interpolation, a 90-day-median personal-baseline
reference line, in-target zone shading, rich tooltips with delta
vs. baseline, and 600 ms ease-out animation that respects
`prefers-reduced-motion`. Sparse data (<3 points) renders an explicit
empty state instead of a degenerate line.
- **Comparison overlay (vs. last month / vs. last year).** A new toggle
at the top of every chart, tile, and the insights surface overlays the
prior period as a dimmed line beneath the current one and adds a delta
callout (Δ ±N). The AI summary narrates the comparison ("your average
BP improved by 4 mmHg vs. last month") when the toggle is active.
- **Settings → Export.** Consolidated `/settings/export` page with one
card per export type: doctor-report PDF (configurable date range +
practice name), measurements CSV, medications CSV (optional intake
history), mood CSV, full JSON backup. Each download writes a
`user.export.<kind>` audit-log entry and shares a 10/h rate-limit
bucket. Doctor-report entry-point relocated under this route.
- **Achievements page.** New `/achievements` page with locked + unlocked
breakdown grouped by category (medication / vitals / security /
engagement). Recent unlocks card on the dashboard, toggleable from
layout settings.
- **Onboarding tour for new users.** First-run spotlight walk-through
highlighting tile-strip, quick-add menu, insights, integrations, and
achievements. Skippable, keyboard-navigable, replayable from
Settings → Account.
- **Admin host-load chart.** New chart over the system-status section
shows host CPU, memory, and disk-IO over the last 2 hours, sampled
every minute, retained for 7 days.
- **Admin app-log preview.** Tail of the last 1 hour of structured
wide-events from the per-process ring buffer, filterable by trace_id /
level / action / time-window with a JSON inspector modal.
- **Admin AI quality preview.** New `/admin/ai-quality` route surfaces
helpful-rate per (severity × provider), tinted by band so degrading
providers stand out at a glance.
### Changed
- **Insights surface uses the new RecommendationCard everywhere.** The
`/insights` page and the dashboard insights tile both render the
polished card — rationale expand, confidence meter, citation footnote,
feedback thumbs — backed by a shared TanStack Query cache.
- **Trend label normalised to "7-day trend".** Every chart, tile, and
subtitle uses the long form. A signed numeric delta indicator (±N.N)
with metric-aware colouring appears next to the value on every chart,
including mood and medication-compliance.
- **`/admin` overview redesigned.** The section grid is gone; the
overview now shows a system-status snapshot with host-load chart and
an audit-log preview. Sidebar carries the section list.
- **Sidebar admin sub-items only expand on `/admin/*`.** Clicking the
Admin link or opening the Gravatar dropdown no longer auto-expands
the sub-list when you are not on an admin route.
- **Settings → AI is a single dropdown.** The provider selector at the
top drives the configuration form below; no more top/bottom split. All
five providers (Codex / OpenAI / Anthropic / Local / Admin OpenAI) are
reachable from the same UI.
- **Top dashboard tiles selectable per metric.** The widget-id enum bug
from v1.4.15 that silently 422'd every layout PUT is fixed; the
per-metric tile toggle in layout settings now actually persists.
- **AI rate-limit raised to 10/hour.** Default bumped from 2/h to 10/h;
configurable via `INSIGHTS_RATE_LIMIT_PER_HOUR`. Generating a new
insight evicts every previously cached per-status insight for that
user, so the dashboard never shows a stale cached payload.
### Fixed
- **BD-Zielbereich percentage now counts in-range readings correctly.**
The v1.4.15 fix corrected the denominator but kept the ESH narrow-band
predicate (`sysLow ≤ sys ≤ sysHigh AND diaLow ≤ dia ≤ diaHigh`), so
normotensive readings (e.g. 117/79) below `sysLow=120` counted as out
of range. Predicate switched to one-sided ceiling semantics with a
hypotension floor (`90 ≤ sys ≤ sysHigh AND 50 ≤ dia ≤ diaHigh`),
centralised in `isBpReadingInTarget()` shared by six call sites.
- **Trend on "all" filter shows a meaningful split-half delta.** Long
windows where the per-week rate fell below the 1-decimal display
precision now also surface a split-half mean delta (second-half mean
minus first-half mean) for windows ≥ 90 days.
- **Login overview no longer strips umlauts.** The geo helper decodes
via `arrayBuffer()` + `TextDecoder('utf-8')` instead of
`Response.json()`, so an upstream proxy stripping the
`Content-Type: charset` parameter cannot poison the umlaut path.
Nürnberg, München, Düsseldorf, Köln, Würzburg, Bückeburg, Weißenfels
all roundtrip correctly.
- **`/admin/api-tokens` table no horizontal overflow on mobile.** The
desktop `<table>` falls back to a card list at `<md` viewports, with
long names + permission badges wrapping cleanly inside the card.
- **Skip-link no longer blocks logo click.** The "Skip to content"
shortcut still leads the tab order but no longer blocks pointer events
on the logo.
- **Bug-Report nav entry follows the admin feature toggle.** When the
admin disables bug reporting the entry vanishes from sidebar,
bottom-nav, topbar, and the error-detail "Report bug" button.
- **Feedback link follows the admin feature toggle.** When feedback
collection is disabled, the UI entry point disappears too.
- **Cached AI insights replaced when the user regenerates.** Generating
a new insight invalidates the per-status `audit_logs` entries plus the
TanStack Query cache, so the dashboard always shows the freshest
payload.
### Performance
- **Comparison overlays computed via reusable bucket-series helper.** No
extra round-trip per chart — the dashboard fetcher and AI snapshot
both read from the same `avg30LastMonth` / `avg30LastYear` fields.
- **`/api/insights/feedback` persists with optimistic UI updates.**
Thumbs-up / thumbs-down apply instantly; the localStorage refresh-
defence keeps the verdict on rerender even before the mutation
resolves.
### Security
- **AI provider apiKeys encrypted at rest.** Provider chain entries that
carry a key store it AES-256-GCM via the existing `src/lib/crypto.ts`
helper.
- **`/api/insights/feedback` gated by `requireAuth` + idempotency-key.**
The dedicated rate-limit bucket prevents thumbs-spam.
- **Per-provider attribution server-filled.** Clients cannot tamper with
which provider gets credit for a recommendation; the attribution is
resolved server-side from the latest `insights.generate` audit row.
- **Admin egress redacts secrets.** Audit-log `details` and app-log
`meta` fields run through `redactSecrets()` before leaving the admin
API surface.
### Internal
- **`docker-publish` workflow no longer hangs on main-branch builds.**
Root cause was a qemu-arm64 SIGILL during multi-arch emulation; arm64
dropped from the platforms list. Native arm64 runner matrix scheduled
for v1.5.
- **CI integration tests + e2e workflows green again.** Both had been
pre-existing red since `d8c549e` (encryption-key YAML scalar parsed
as integer 0 + spotlight tour overlay intercepting clicks). Both fixed
this milestone.
### Deferred to v1.5
- Coolify image-digest auto-deploy trigger (currently fires on every
git-push; Marc-side UI flip is the realistic fix).
- Native arm64 runner matrix for full multi-arch docker publish.
- Cross-user feedback aggregation prompt-tuning ratchet (depends on
v1.4.16 feedback collection accumulating data).
- Dedicated `/insights/compare` page (i18n keys
`comparison.insightsCallout.{lastMonth,lastYear}` reserved).
## [1.4.15] — 2026-05-09
### Added
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "healthlog",
"version": "1.4.15",
"version": "1.4.16",
"private": true,
"packageManager": "pnpm@10.31.0",
"scripts": {