One-shot prettier pass so the new format:check gate starts from a clean
baseline. Formatting only — no behaviour change. Generator-owned and
vendored artifacts stay untouched via .prettierignore.
The project licence changes from AGPL-3.0 to the PolyForm Noncommercial
License 1.0.0 for this and future versions: free to use, modify and
self-host for noncommercial purposes; commercial use needs a separate
arrangement. Releases up to and including v1.15.18 were published under
AGPL-3.0 and remain available under that licence. LICENSE carries the
verbatim PolyForm text, and the SPDX identifier is updated in
package.json, the version endpoint, the OpenAPI info block, the image
labels and the README.
iOS-operator-blocking hotfix for REG-11 — Home dashboard tile renders
neither chart nor latest value for BP / Puls / Körperfett when the
most recent reading is older than 7 days. Root cause was in
`/api/dashboard/summary` SQL gates; `latestIn7d` + `sparkBuckets` both
required `measured_at >= sevenDaysAgo`, which returned empty for
sparse accounts, leaving the iOS tile with `latestValue: null` +
`sparkline: []` to render from. Detail-screen
(`/api/measurements/series?kind=…`) escaped because of its broader
window.
Server-side changes:
- `latestIn7d` → `latestEver` (drops 7-day filter; DISTINCT ON returns
latest reading EVER per type, bounded at N_metrics rows).
- `sparkBuckets` rewritten via ROW_NUMBER() OVER (PARTITION BY type
ORDER BY bucket_start DESC) so the trailing N daily buckets per
type render regardless of age, bounded at SPARK_DAYS × N_metrics.
- BP + Pulse metrics.push gated on `latest || allTimeCount > 0` like
BodyFat already is — accounts with zero readings ever no longer get
empty placeholder tiles.
- 4 new regression tests in summary/__tests__/route.test.ts cover
sparse accounts, zero-data accounts, within-7d guards.
Other develop work bundled in this release:
- W4-QoL — copy nits.
- W5-WORKOUTS — user source priority threaded through write-time
picker + batch route.
- W7-WITHINGS-RELIABILITY — response classifier + sync hardening.
- W8-OPS — ops phase docs.
- B11 — NEXT_PUBLIC_APP_VERSION build-arg routing so /api/version
cannot drift from CI tag.
- env-check workflow — manifest / example lockstep enforcement.
Resolves PR #194 (squash-merge produced via local -X theirs strategy
because GitHub's UI couldn't auto-resolve develop's post-v1.4.42
contiguous work against the v1.4.42 squash on main; resulting tree is
byte-identical to develop's HEAD).
## [1.4.28.1] — 2026-05-16 — Dashboard-save hotfix
"Speichern" on the Dashboard works again for every account whose
layout was last persisted before v1.4.28. The v1.4.28 retire of the
`glp1` widget id left an orphan entry in `dashboardWidgetsJson` for
legacy users, which made the save validator reject the payload; the
resolver now filters unknown widget ids on read.
### Fixed
- **Dashboard save against legacy layouts.**
`resolveDashboardLayout` in `src/lib/dashboard-layout.ts` drops
widget ids that are no longer in the registry before returning
the layout, so the `dashboardWidgetsJson` round-trip
(`GET /api/me/dashboard` → user edit → `PUT /api/me/dashboard`)
succeeds even when the persisted JSON still names `glp1` or any
other retired widget.
### Tests
- `src/lib/__tests__/dashboard-layout.test.ts` gains a case for the
retired-id filter (19/19 green).
Adds a public GET endpoint that exposes the running build's version,
optional Git SHA, optional ISO build timestamp, license, and
canonical links (repository, changelog, docs site). Three consumers
already lined up against this:
- The Settings → About section (v1.4 plan A3) renders version + build
metadata + a "Check for updates" button.
- The footer of every page can show the version dezent without
another roundtrip.
- The "Check for updates" button compares the returned version
against the GHCR API.
Build-time env vars (`NEXT_PUBLIC_APP_BUILD_SHA`,
`NEXT_PUBLIC_APP_BUILT_AT`) are read straight off `process.env` —
the existing `docker-publish.yml` workflow can wire them once it
needs to. Local `pnpm dev` returns `null` for both fields and the UI
falls back to "development" wording.
Static export (`force-static`) so the endpoint adds zero load on the
DB and survives in the static-cache page chunks.
Tests: 395 → 400 (+3 for the version envelope shape and env-var
plumbing). The remaining About UI lands in a follow-up so this PR
stays scoped to the API contract.
Co-authored-by: Marc-André Bombeck <noreply@anthropic.com>