Commit Graph
572 Commits
Author SHA1 Message Date
Marc-André Bombeck f41605efba Close two high advisories on the outbound path
`undici` moves to 8.10.0 and the `fast-uri` override rises to 3.1.5. Both were
published as high after the last run on the trunk, so this is new information
rather than neglect, and both matter here: undici is what backs `safeFetch`,
which is the one documented egress boundary and the place the connect-time
DNS-rebinding pin lives.

The undici advisory is a cross-user information disclosure and a parse-time
crash through degenerate private cache directives. `fast-uri` arrives four ways
through transitive dependencies and the existing override was pinned one patch
short of the fix.

The safe-fetch dispatcher suite passes against the new client, which is the
part that had to be checked rather than assumed: the pin reaches into undici's
connect hook and a client bump is exactly where that could quietly stop being
enforced.
2026-08-03 22:10:15 +02:00
dependabot[bot] 9e61e73dec build(deps-dev): bump shadcn from 4.13.0 to 4.16.1
Bumps [shadcn](https://github.com/shadcn-ui/ui/tree/HEAD/packages/shadcn) from 4.13.0 to 4.16.1.
- [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.16.1/packages/shadcn)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-03 16:15:56 +00:00
Marc-André Bombeck a0fc404fb8 Merge pull request #697 from MBombeck/dependabot/npm_and_yarn/tanstack/react-query-5.101.4
build(deps): bump @tanstack/react-query from 5.101.2 to 5.101.4
2026-08-03 18:13:01 +02:00
Marc-André Bombeck e621da670c Merge pull request #696 from MBombeck/dependabot/npm_and_yarn/react-hook-form-7.83.0
build(deps): bump react-hook-form from 7.81.0 to 7.83.0
2026-08-03 18:12:53 +02:00
Marc-André Bombeck 5da64628ec Merge pull request #695 from MBombeck/dependabot/npm_and_yarn/eslint-config-next-16.2.12
build(deps-dev): bump eslint-config-next from 16.2.6 to 16.2.12
2026-08-03 18:12:46 +02:00
dependabot[bot] 15bd7e660a build(deps): bump react-hook-form from 7.81.0 to 7.83.0
Bumps [react-hook-form](https://github.com/react-hook-form/react-hook-form) from 7.81.0 to 7.83.0.
- [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.81.0...v7.83.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-03 11:03:27 +00:00
dependabot[bot] ad18303f7e build(deps-dev): bump eslint-config-next from 16.2.6 to 16.2.12
Bumps [eslint-config-next](https://github.com/vercel/next.js/tree/HEAD/packages/eslint-config-next) from 16.2.6 to 16.2.12.
- [Release notes](https://github.com/vercel/next.js/releases)
- [Commits](https://github.com/vercel/next.js/commits/v16.2.12/packages/eslint-config-next)

---
updated-dependencies:
- dependency-name: eslint-config-next
  dependency-version: 16.2.12
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-03 11:03:23 +00:00
dependabot[bot] 02ff6dff2b build(deps): bump @tanstack/react-query from 5.101.2 to 5.101.4
Bumps [@tanstack/react-query](https://github.com/TanStack/query/tree/HEAD/packages/react-query) from 5.101.2 to 5.101.4.
- [Release notes](https://github.com/TanStack/query/releases)
- [Changelog](https://github.com/TanStack/query/blob/main/packages/react-query/CHANGELOG.md)
- [Commits](https://github.com/TanStack/query/commits/@tanstack/react-query@5.101.4/packages/react-query)

---
updated-dependencies:
- dependency-name: "@tanstack/react-query"
  dependency-version: 5.101.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-03 11:03:20 +00:00
dependabot[bot] 8779fb9cc9 build(deps): bump @prisma/adapter-pg from 7.8.0 to 7.9.1
Bumps [@prisma/adapter-pg](https://github.com/prisma/prisma/tree/HEAD/packages/adapter-pg) from 7.8.0 to 7.9.1.
- [Release notes](https://github.com/prisma/prisma/releases)
- [Commits](https://github.com/prisma/prisma/commits/7.9.1/packages/adapter-pg)

---
updated-dependencies:
- dependency-name: "@prisma/adapter-pg"
  dependency-version: 7.9.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-03 11:03:01 +00:00
Marc-André Bombeck 314bf26638 chore(release): v1.36.0 — one record, two people, and a line that says which 2026-08-02 20:28:53 +02:00
Marc-André Bombeck 3cf2cb417f chore(release): v1.35.6 — one line where there were two 2026-08-02 07:29:42 +02:00
Marc-André Bombeck c9ee84e5e4 chore(release): v1.35.5 — a read stops deciding what gets written 2026-08-02 01:30:12 +02:00
Marc-André Bombeck 2618a7ae71 chore(release): v1.35.4 — the checks tell the truth about the calendar and about themselves 2026-08-02 00:38:01 +02:00
Marc-André Bombeck ffe5545032 chore(release): v1.35.3 — an ECG arrives on its own, and only once
Apple Watch ECG recordings reach the record straight from the app instead of
only through an export archive. One recording per request, gated by the same
switches that already govern reading them.

A recording is now identified by what it is rather than by what a source calls
it, so the same strip arriving through both doors converges on one row. The
migration that adds the constraint resolves the duplicates already stored: it
keeps the row holding the waveform over one holding only a verdict, and moves a
removed row's event link onto the row that is kept. The losing rows are deleted.
2026-08-01 19:54:08 +02:00
Marc-André Bombeck 99ceb236de chore(release): v1.35.2 — one answer, published
The cycle ring stops working out its own verdict and reads the server's. The
constant that made that possible is deleted rather than deprecated, because a
constant left in client code is a constant that gets copied again, which is how
the other client's ring froze in the first place.

The score settings page takes the shape the other settings cards have, loses a
pillar that could never score, and turns green where the app's other two scores
already did. A saved selection now comes back as it was sent.

Five gaps in the published specification are closed, including a route that
shipped this morning and was never described at all.
2026-08-01 12:16:27 +02:00
Marc-André Bombeck 7231c9f3f7 chore(release): v1.35.1 — stop asking for a weekly dose that was already taken
A medication on a rolling interval had its expected dose anchored on the moment
the person actually injected, and was then checked off against the moment it was
planned for, with six hours of tolerance. Those two are allowed to sit days
apart, because a dose taken late still counts, so the dose someone's own
injection created could never be marked done. It stayed open, went overdue, and
the app asked for it again.

No editing was needed to reach it. Taking a weekly dose a few days late was
enough, on any account. Push reminders read the plan rather than the entries and
were never affected, so this was on screen, not on a phone.
2026-08-01 10:28:40 +02:00
Marc-André Bombeck b85a348891 Give the type check the same memory ceiling the build already has
CI died at the 4 GB default heap while checking types. The build was given its
own ceiling earlier this month so a local run, CI and the published image all
invoke it the same way; the type check was left on the default and has now grown
past it. Same treatment, same reason.

Also raises the aggregate bundle cap from 3260 to 3310 KB, and only that one.
Every per-route ceiling is untouched and every measured route sits within a
kilobyte of its previous value, so nothing a person downloads grew. The rise is
the new score-settings route, a mutually exclusive chunk that the whole-build sum
counts even though no single visit pays for it, plus its strings across six
locales. The reasoning is recorded in the budget file beside the number.
2026-07-31 22:08:05 +02:00
Marc-André Bombeck 778725834f chore(release): v1.35.0 — the score you decide
The Health Score stops being a by-product of switches meant for something else.
It gets its own page, its own recorded history with the recipe that made each
day, and a comparison that refuses to draw a line across two different
definitions.

An account that upgrades keeps the composition it already had, so the number
does not move on its own. What changes is that the composition is now visible
and yours.
2026-07-31 20:32:25 +02:00
Marc-André Bombeck 7b9cde7a24 chore(release): v1.34.5 — the score says where its numbers come from
Version anchors, the regenerated service-worker version and API spec, and
the changelog entry.
2026-07-31 11:59:57 +02:00
Marc-André Bombeck 001641f57e chore(release): v1.34.4 — one question, one answer
Every fix in this release is the same shape underneath. Two places in the code
were each deciding something they both had to agree on, and nothing made them
agree: two copies of the due-day rule, two clocks on one card, two server caches
behind one page, two ideas of where a nap belongs.

The version anchors, the changelog and the published specification move together
as usual.
2026-07-31 08:29:37 +02:00
Marc-André Bombeck 4c35c16d64 chore(release): v1.34.3 — say the thing the surface already knew
Thirty-four changes, most of them one shape: something the server or the screen
already knew and did not say. A closed schema that omitted three fields it sends.
A fence around sensitive data that the contract never described, so the native
client dropped an affordance rather than risk crossing it. An ingest whose only
durable trace fired on success, leaving "did the phone even post" unanswerable. A
profile save that discarded valid fields to punish an invalid neighbour. A card
titled "that day" that received the day and threw it away.
2026-07-31 01:27:29 +02:00
Marc-André Bombeck b767cff187 build: carry the heap ceiling in the build script itself
`next build` needs more than Node's 4 GB default: the TypeScript pass after
compilation runs the whole project through the checker and dies with
"Ineffective mark-compacts near heap limit" at around 4.07 GB.

CI and the production image already knew that. `e2e.yml` and the Dockerfile both
invoke the build with `--max-old-space-size=8192`. The bare `pnpm build` did not,
so the one place that ran with the default was a local gate — which then failed
for a condition that exists in neither environment that matters, and would have
kept failing every time somebody ran the documented gate.

Three places declared how the build is invoked and one of them disagreed. The
script now carries it, so a local run, CI and the image all get the same ceiling.
The existing prefixes in the workflow and the Dockerfile stay: they are harmless
now, and removing them would put the knowledge back in more than one place.
2026-07-30 18:35:38 +02:00
Marc-André Bombeck b8c9a519c1 chore(release): v1.34.2 — count a re-sent workout once on every surface; re-anchor the service-worker version
Carries the four fixes that landed after the v1.34.1 tag plus the two found while
reviewing them.

The workout collapse that shipped in that batch only worked on the workout list,
because it keyed a session on a field three of the five callers never fetched.
Those three kept averaging one session into a person's baseline more than once.
The service-worker fallback version had drifted a release behind with nothing
checking it; both halves now have a gate.
2026-07-30 11:58:20 +02:00
Marc-André Bombeck b1e20f59dc release: prepare v1.34.1 2026-07-29 17:31:31 +02:00
Marc-André Bombeck 17e09345d2 chore(release): v1.34.0 — a failure looks like a failure, a number is yours or it says so 2026-07-28 21:49:56 +02:00
Marc-André Bombeck 4d459dbb68 chore(release): v1.33.2 — the cycle-symptom fix that did not reach the file
v1.33.1 claimed custom cycle symptoms were carried in backups. They were not,
and the same release turned the old silent drop into a hard failure, so the
accounts the fix was written for went from losing one symptom link to being
unable to restore at all.
2026-07-28 00:09:29 +02:00
Marc-André Bombeck 4d1d712b93 chore(release): v1.33.1 — what the app knew and did not say
Eight workstreams, two migrations, and a pass by an independent reader that
found four things this release was claiming about itself that were not true.

Two of the fixes change what people receive. Medication reminders went out
every fifteen minutes because the dedup key could not tell one dose slot from
another, and "handled by the app" was silencing every channel rather than the
one it names. Both are called out in the notes, because a user who set that
flag as a general mute will notice.

Two came from reports: an OpenAI-compatible gateway that the provider list
had no room for, after an earlier answer from us said otherwise, and four
places where a timestamp followed the browser instead of the profile.

The backup half is the one worth reading. Three record types were carried and
could not be restored, or could not be carried at all, and each failed in a
different direction: one dropped silently, one stopped the restore outright,
one was discarded while the restore reported success. What a backup holds is
now declared in one file with a written reason for everything left out, and
the roughly thirty types that are still carried by neither end are named there
instead of waiting to be discovered by someone who needed them.
2026-07-27 17:41:50 +02:00
Marc-André Bombeck 4be01a67f0 chore(release): fold in the coach discriminant, the dependency bumps, and the notes the audit found wrong 2026-07-26 18:57:21 +02:00
Marc-André Bombeck dbac3d3abd chore(release): v1.33.0 — what was silently failing 2026-07-26 18:18:28 +02:00
Marc-André Bombeck e67bb25338 chore(release): v1.32.39 — the doctor report carries only what was chosen 2026-07-26 01:12:03 +02:00
Marc-André Bombeck ec49157e85 chore(release): v1.32.38 — accept a blood-glucose reading that carries no context 2026-07-25 22:18:03 +02:00
Marc-André Bombeck 132238fd05 chore(release): v1.32.37 — refuse an identity that cannot be stable, and scope the intake replay key to its owner 2026-07-25 19:14:30 +02:00
Marc-André Bombeck 7c66413c1d chore(release): v1.32.36 — make the loose-ends failure class hard to reintroduce 2026-07-25 16:24:29 +02:00
Marc-André Bombeck fe2e20a14b chore(release): v1.32.35 — remember the practice name, keep the source provenance in a backup 2026-07-25 15:28:39 +02:00
Marc-André Bombeck c623745942 chore(release): v1.32.34 — one shell and one rhythm for the insights overview
Interface housekeeping. The overview sections drop their hand-rolled card
frames for a shared shell with one inner rhythm, failed reads on dense metric
pages get a named row primitive that puts the message in the content tier, and
the last off-scale spacing and text sizes go back onto the scale.

The tag chip and the sub-twelve-pixel text step are primitives now, so neither
can be hand-copied at a slightly different value again.
2026-07-25 14:21:30 +02:00
Marc-André Bombeck a006f76320 chore(release): v1.32.33 — remove the moodLog integration
Version bump, regenerated OpenAPI spec (version field only; the moodLog routes
were never registered on the public contract), and the release notes.
2026-07-25 11:36:33 +02:00
Marc-André Bombeck e657bf928e chore(release): v1.32.31 — the integrations page says what is actually happening 2026-07-25 09:41:58 +02:00
Marc-André Bombeck 41c2213fe6 chore(release): v1.32.30 — height is entered and shown in the unit you use 2026-07-25 08:21:57 +02:00
Marc-André Bombeck fb74b686e3 chore(release): v1.32.29 — a re-scored Fitbit night stops double counting
Stable per-segment sleep keys plus the replace-by-window sweep, a one-shot
repair over the past year, Retry-After handling, and the unchanged-value write
skip. Migration 0270 records which connections the repair has been through.
2026-07-25 06:15:37 +02:00
Marc-André Bombeck 40a746b2b7 chore(release): v1.32.28 — Oura catches up after a gap; manual sync for the last four providers 2026-07-25 04:43:18 +02:00
Marc-André Bombeck 7a4e819679 chore(release): v1.32.27 — target and threshold panels follow the unit preference 2026-07-25 03:24:24 +02:00
Marc-André Bombeck a9b2ab2d2b chore(release): v1.32.26 — apply the metric/imperial preference across every reading surface
Surface a self-hoster's report that the unit preference was stored but read by
almost no display. Weight, body composition, waist, and temperature now follow
metric or imperial at entry and everywhere they render, storage stays canonical
SI, and the MCP logging tool converts a known unit hint or refuses an unknown
one. OpenAPI diff is version-only; the wire stays canonical.
2026-07-25 00:35:07 +02:00
Marc-André Bombeck bb79d28911 chore(release): v1.32.25 — surface mirrored-medication provenance and cap external mirror growth 2026-07-24 23:18:26 +02:00
Marc-André Bombeck 4ac39a7052 chore(release): v1.32.24 — isolate Polar collections and log envelope drift
Per-collection isolation for the Polar vitals sync: one unavailable data type
no longer blanks the rest, a failing collection is named on the integration
status, and an unexpected response shape is logged instead of reading as no
data. Bump version, regenerate the OpenAPI version string, add the changelog
entry.
2026-07-24 21:26:35 +02:00
Marc-André Bombeck bb631de7c8 chore(release): v1.32.23 — honest sync status across the non-sensitive providers
A failed sync no longer reads as success across WHOOP, Withings, Oura, Polar,
Nightscout, and Strava: a dead WHOOP token stays parked instead of flipping back
to connected, an interrupted history backfill is retried rather than marked
complete, Withings ECG syncs on its own hourly schedule, activity and sleep
write failures surface on the status card, poll-cohort sync errors that
previously vanished are recorded, and Strava history import starts at connect
time.
2026-07-24 20:06:06 +02:00
Marc-André Bombeck e65390792d chore(release): v1.32.22 — extend the concurrent-edit guard to the prefs records; serialise the inventory and privacy races 2026-07-24 18:08:15 +02:00
Marc-André Bombeck ab03bc96f1 feat(concurrency): guard layout and about-me writes against a concurrent overwrite
Extract the dashboard-layout optimistic-concurrency mechanism (issue #581)
into a shared server helper (takeBaseToken plus guardedUserUpdate /
guardedRowUpdate) and a client helper (readUpdatedAtToken, withBaseToken,
isConflict). Retrofit the dashboard-widgets route onto the helper and apply the
same guard to the insights layout, medications layout, and coach about-me write
endpoints.

A request that omits the base token keeps the byte-identical unconditional
write, so older clients are unaffected. Document the contract in the OpenAPI
registry, including the dashboard-widgets path that was previously absent.
2026-07-24 16:26:58 +02:00
Marc-André Bombeck 0317942f1c chore(release): v1.32.20 — screen the medication-adherence card and background lines like every other insight 2026-07-24 15:18:26 +02:00
Marc-André Bombeck 15b8df11bc chore(release): v1.32.19 — clear the Today view the instant a write lands
A dose logged from another screen marked the Today hero and the dashboard
stale without re-reading them, so returning to the home page kept showing the
old state until the 120 s poll or a hard reload. The daily reads run with
refetchOnMount off, so a bundle invalidation with the default active
refetch-type never touched them while they were unmounted.

Route every intake-affecting medication write through one blessed
invalidateMedicationReads (bundle invalidation plus a forced inactive refetch
of the digest and snapshot): Take all due, the intake edit dialog, the history
bulk/row delete, the dose-history ledger and its add dialog, the lifecycle and
danger-zone actions, and the intake import. Give the Vorsorge reminder
mutations the same daily-rail refresh, bust the biomarker assessment and the
labs-changes read after a lab write, and refetch the daily reads after a
briefing regenerate so the Today lead updates without a reload.

Restore the dashboard-layout concurrency belt: the settings layout query now
always loads its own tokened copy, so a home-page visit can no longer strand a
save without its base token and silently drop the v1.32.16 conflict guard.

Add a structural guard that fails CI when a new site invalidates a daily-reads
bundle without the paired inactive refetch, so this class cannot recur a
fourth time, plus behavioural coverage for the batch take and the Vorsorge
refresh.

Refs #581
2026-07-24 13:56:22 +02:00
Marc-André Bombeck 115c3e3dcd chore(release): v1.32.18 — a dead Fitbit token no longer stamps a successful sync
Hold the Fitbit sync verdict when the token is dead or a write fails, and
verdict-gate the history backfill so a partial first-time import retries
instead of marking itself complete. No schema or contract change; the OpenAPI
version string tracks the bump.
2026-07-24 13:00:27 +02:00