Bucket B of the v1.4.3 polish pass.
Three issues, one commit because they're the same surface:
1. **API & Tokens tables overflowed the settings content column.**
Each table set `min-w-[760px]` (or 860px) so the table never
compressed below that width. On mobile this is intentional (it
gives the inner cells breathing room while the outer wrapper
horizontally scrolls). On md+ the parent column is smaller than
the min-width on common laptop sizings (~800px content area when
the browser isn't full-width), which forced an inline scrollbar
for no benefit. Switched to `min-w-[760px] md:min-w-0` per table
so the constraint releases at the breakpoint where the layout
stops scrolling.
2. **"Auf Updates prüfen" button silently did nothing.** The
client-side handler called `https://api.github.com/.../releases/
latest` directly. Production CSP locks `connect-src` down to
`'self'` + `https://wbsapi.withings.net`, so the fetch was
blocked at the browser before it left the tab. Replaced with a
server-side proxy at `/api/version/check-updates` that fetches
GitHub for the user, compares the running `package.json` version
against `tag_name`, and returns one of `up_to_date | newer_
available | unknown`. The route is auth-gated (cookie OR bearer)
so anonymous traffic can't burn through GitHub's 60-req/hr anon
rate limit on the deployment's IP. The route also annotates the
external call into the Wide Event so a future spike is visible
in the logs.
3. **The About surface had no headings and a stray Badge box.** The
v1.4.2 version put the License inside a `<Badge variant=
"outline">`, which created a small framed pill that read as a
separate widget rather than a peer of the version number. Below
that, the Sources/Changelog/Docs and the update-check button
each lived in their own card with no h2 — three nameless cards
stacked on the page. Restructured into three titled cards:
- **HealthLog** — identity, with version + license rendered
inline as plain monospace pairs (no Badge, no nested grid).
Build SHA + build timestamp ride along on the same row when
set.
- **Quellen & Dokumentation / Sources & docs** — links unchanged
but now under their own h2.
- **Updates** — manual `Check now` button + a passive "Last
checked: …" line that pulls from localStorage so the user
can see when the previous check ran. On mount, if the last
successful check is >24h ago (or has never run), the page
auto-checks once. The 24h window is a deliberate compromise
between "always fresh" and "GitHub anon rate limit". The
error path renders a non-blocking "Couldn't reach GitHub"
message with the alert role so screen readers announce it.
i18n keys touched in both `de.json` + `en.json`:
- `settings.about.linksHeading` (new)
- `settings.about.updatesHeading` (new)
- `settings.about.checkUpdates` (label shortened)
- `settings.about.checking` (button busy state — new)
- `settings.about.lastChecked` / `lastCheckedNever` (new)
- `settings.about.checkFailed` (new — replaces the misleading
`testConnection.errors.connection_failed` reuse)
Tests updated for the new heading + button strings; 669/669 green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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>