Commit Graph
1422 Commits
Author SHA1 Message Date
Marc-André Bombeck 73bb13a982 feat(anamnesis): soft-delete AUDIT-C in its route, admit both AUDIT-C verbs at manage level, and settle the guards 2026-10-16 01:24:56 +02:00
Marc-André Bombeck 28a8737124 feat(anamnesis): life-circumstances card with AUDIT-C, screening hints and free-text take-over 2026-10-16 01:09:50 +02:00
Marc-André Bombeck 0dd634c9c8 Merge branch 'v143/links' into release/v1.43.0
# Conflicts:
#	docs/api/openapi.yaml
#	src/__tests__/contract-stub-inventory.test.ts
#	src/app/api/medications/[id]/route.ts
#	src/components/medications/detail/medication-detail-tabs.tsx
#	src/lib/export/backup-plan.ts
2026-10-16 00:34:53 +02:00
Marc-André Bombeck 3fc37c9183 Merge branch 'v143/ios' into release/v1.43.0 2026-10-16 00:28:40 +02:00
Marc-André Bombeck 6146082824 Merge branch 'v143/supplements' into release/v1.43.0
# Conflicts:
#	docs/api/openapi.yaml
#	messages/de.json
#	messages/en.json
#	messages/es.json
#	messages/fr.json
#	messages/it.json
#	messages/ko.json
#	messages/pl.json
#	src/__tests__/sharing-surface-guard.test.ts
#	src/lib/ai/capabilities/types.ts
#	src/lib/export/backup-plan.ts
2026-10-16 00:28:29 +02:00
Marc-André Bombeck 1481e38fae feat(links): show related records and file the new pairs on the web
A shared related-records component renders related[] as rows that open the
server-resolved path, with how a derived relation runs. The medication
overview lists them and, in the account's own record, files its condition,
documents and visits; the visit sheet files medications and doses. The
condition page, the document sheet and the dose sheet list what their own
blocks do not already show. A dose's visit named by the form's field counts
as the same relation as the link table.
2026-10-16 00:25:04 +02:00
Marc-André Bombeck a0f6b89e92 feat(measurements): take hourly sums of summed types into the intraday profile and a backfill trigger that moves no live stamp; fix(backup): restore qualitative lab markers 2026-10-16 00:18:35 +02:00
Marc-André Bombeck 5c039a220b Merge branch 'v143/sso' into release/v1.43.0
# Conflicts:
#	docs/api/openapi.yaml
#	src/__tests__/contract-stub-inventory.test.ts
2026-10-15 23:59:03 +02:00
Marc-André Bombeck ffd46b017b feat(backup): carry the five relation link tables both ways
Lab result to document, visit to medication, visit to dose, medication to
document and medication to condition now ride the full backup in their own
section file and come back with their original filing instant. A link whose
end the restore did not write is dropped and reported under the new
relationLink skip kind. The tables leave the coverage register for the
two-ended list, guarded by relation-links-backup-completeness.test.ts and
seeded in the round trip.
2026-10-15 23:57:27 +02:00
Marc-André Bombeck 01fef691fa feat(web): edit a supplement's composition, read it from a label photo, and show nutrient sources with the upper limit 2026-10-15 23:48:43 +02:00
Marc-André Bombeck 79f7eb199b feat(insights): resolve direction verdicts, chart reference lines and mood patterns on the server 2026-10-15 23:39:11 +02:00
Marc-André Bombeck 9d32a8acb0 feat(medications): let a delegate manage a composition, bypass the proxy for label uploads, and keep the guards current 2026-10-15 23:37:26 +02:00
Marc-André Bombeck 0ebb61343e feat(claim): offer the identity provider on the claim page and name the way in to guardians
The claim page shows the password form, a continue-with-provider button, or
both, as the preview names them, and explains a refused single-sign-on claim
when the callback sends the browser back. The guardian's handover panel says
how the person will sign in.
2026-10-15 23:34:38 +02:00
Marc-André Bombeck 98d64c2052 feat(nutrients): add DHA, EPA, input units and upper limits to the catalogue, and count supplement doses as a nutrient source 2026-10-15 23:19:45 +02:00
Marc-André Bombeck b91328d67e feat(records): publish an age- and sex-aware benchmark beside each personal record 2026-10-15 23:18:58 +02:00
Marc-André Bombeck b562587c45 feat(cycle): name the start a period start folds in and the starts a removal gives back 2026-10-15 23:16:11 +02:00
Marc-André Bombeck fd44a8381b Merge branch 'v143/ai' into release/v1.43.0
# Conflicts:
#	docs/api/openapi.yaml
#	messages/de.json
#	messages/en.json
#	messages/es.json
#	messages/fr.json
#	messages/it.json
#	messages/ko.json
#	messages/pl.json
#	src/__tests__/contract-stub-inventory.test.ts
2026-10-15 23:12:51 +02:00
Marc-André Bombeck 74fa4e10b6 Merge branch 'v143/labs' into release/v1.43.0 2026-10-15 23:06:51 +02:00
Marc-André Bombeck e112e05a58 fix(labs): name a merge in the owner's activity feed and toast it through the outcome module
A merge by a record manager now reads as its own sentence in the owner's
activity feed, the merged toast goes through the written-outcome toast,
and the export test doubles carry the alias and merge tables.
2026-10-15 23:03:45 +02:00
Marc-André Bombeck ec67663def feat(settings): choose the AI usage level, and set its bounds as an operator
Settings, AI gains one card with the three levels, each with what it does
and the server's estimate of tokens per day, labelled as one. Levels above
the operator's ceiling are shown disabled with the reason; a capped choice
is named and kept; a stored choice can return to the server default. The
automatic document read says when the frugal level rests it. Admin, Coach
gains the ceiling, the default and the sync gap, and the provider readout
the accounts per level. Strings in all seven languages.

The admin card's save confirms with a success toast like its neighbour
assistant-section; it is a settings write without counts, so it is pinned
in the success-affordance guard at one.

Refs #1217
2026-10-15 22:55:40 +02:00
Marc-André Bombeck e65ada2961 feat(labs): merge markers, edit their aliases and pick a marker on review
The marker list offers a merge with the server's preview: what moves, what
is converted, which names become aliases, and a refusal when a unit cannot
be converted; it says a merge cannot be undone. The marker page shows and
edits the other spellings and follows a merged marker to its target. Scan
and document review name the matched marker or offer its suggestions and a
new marker; the choice is remembered. The biomarkerMerge feature flag is
on.
2026-10-15 22:55:08 +02:00
Marc-André Bombeck f7386742b4 feat(web): show the error id on server failures and add the support info and report surfaces 2026-10-15 22:31:51 +02:00
Marc-André Bombeck a3ce6af9a3 feat(labs): resolve marker names through aliases and catalog shorthand
A printed name now resolves to one of the account's markers by its own
name, then by an alias of the account, then by a catalog name for the same
analyte when the reading's unit fits. The catalog gains seeds for alkaline
phosphatase and total bilirubin and a checked list of common lab shorthand
in seven languages; names that mean two analytes stay out.
2026-10-15 22:22:29 +02:00
Marc-André Bombeck e16c9fb717 feat(links): search a year or a month in the link pickers by its date window
A picker term that names a period ("2019", "03.2019", "2019-03",
"März 2019", "2019년 3월") is sent as the list route's from/to window
instead of q, newest first, on every family including the visit list,
which has no text search. Month names come from Intl for the UI locale,
folded for case, accents and umlaut spellings. Instant routes get the
period's bounds in the person's timezone; the document route gets the
period's calendar days. The sheet names the period it shows.
2026-10-15 22:11:49 +02:00
Marc-André Bombeck 03b24461ad feat(healthkit): record Apple Health dose arrivals and the last background arrival per type
Migration 0401 turns healthkit_type_syncs.type into text so the ledger can
hold MEDICATION_DOSE, and adds last_background_at (seeded from rows whose
latest arrival was a background one). POST /api/medications/intake/bulk
takes syncTrigger and records APPLE_HEALTH dose arrivals; the Apple Health
status read serves a MEDICATION_DOSE freshness entry and lastBackgroundAt
on every entry with arrival facts.
2026-10-15 15:33:30 +02:00
Marc-André Bombeck 6313c0174a Merge branch 'v1424/readiness' into release/v1.42.4 2026-10-15 15:24:29 +02:00
Marc-André Bombeck f95c2bfd41 Merge branch 'v1424/cards' into release/v1.42.4 2026-10-15 15:22:12 +02:00
Marc-André Bombeck 73922c039e fix(insights): say what fills the recovery page when it is empty
The empty note told a connected Oura account to connect Oura. The page
charts the WHOOP and Polar recharge, strain and load readings and the
Oura resilience level; Oura's readiness is the recovery score linked
above. The note now says so.
2026-10-15 15:10:18 +02:00
Marc-André Bombeck 1a5b09a73c feat(settings): one integration card for every connection
Every connection in Settings renders the same card from the server's health
field: a badge with one word, one sentence per reason, the newest data as a
meta line, a collapsed details block whose text is exactly what the copy
button copies, and an action row with the rare actions in a menu and at most
one primary button. The per-provider banners, the raw provider error line,
the token expiry, the failure counter and the button rows are gone; every
capability they carried is reachable from the sentence, the one button, the
menu or the details. The managed-profile view renders the same card,
read-only. A structural guard keeps the cards off the retired fields.
2026-10-15 15:06:03 +02:00
Marc-André Bombeck 7c905249fb fix(medications): page the side-effect list and name every GLP-1 medication in the timeline 2026-10-15 15:05:51 +02:00
Marc-André Bombeck 73c4dda224 fix(visits): reach every lab result, condition, document and visit from the link pickers
The visit form's lab picker offered the newest 200 results, the condition
picker the newest 100 conditions, the document pickers the newest thousand
documents and the document sheet's visit picker the newest 100 visits.
On a long record everything older could not be linked.

Each picker now opens on the records around the date of the thing being
linked, pages older and newer from there, and searches through the list
route itself. Records already linked always show, from the labels the
record's own read carries and from what was picked in the sheet.

The lab list takes a q filter over analyte and panel, the condition list
from/to/q/offset/sortDir, and the visit list an offset.
2026-10-15 11:24:40 +02:00
Marc-André Bombeck 42b66b2228 Merge branch 'v1423/labs' into release/v1.42.3 2026-10-14 19:34:44 +02:00
Marc-André Bombeck 47a91d6922 fix(labs): never present a converted reading's printed range in the wrong unit
A converted reading's bounds move with its value, but the printed range text
stays in the unit the report used, and every reader preferred that text: the
list showed "Report range 3.9 to 5.5" beside 100.9 mg/dL, and the doctor
report and the FHIR referenceRange.text did the same. The text is still
stored verbatim. The range resolver now takes the reading's sourceUnit (as a
required field, so no reader can forget to select it) and, for a converted
reading, leaves the window's text empty so every surface states the converted
bounds in the marker's unit, and hands the printed text over separately with
its unit. The lab DTO carries it as printedReferenceText, and the note beside
a reading shows it as "as printed in mmol/L: ...".
2026-10-14 19:10:49 +02:00
Marc-André Bombeck 044f9008ba fix(oura): ask for the spo2 and heart_health scopes, explain a missing scope calmly
Oura's current authorization server enforces scopes per collection.
daily_spo2 needs spo2; vO2_max, daily_cardiovascular_age and
daily_resilience need heart_health. The authorize request now asks for
both.

A grant issued before keeps answering 401 on those four collections
while every other one succeeds. Such a 401 next to a success is now
recorded as a scope gap rather than a failure: it no longer counts
toward the reconnect threshold, it no longer forces a token refresh once
known, and the Oura card asks for one reconnect instead. The Withings
card names the readings the account's API plan withholds.
2026-10-14 19:01:02 +02:00
BernhardBuckel 747e0964ad feat(labs): show a reading's conversion in the scan review and beside the value
Slice 3 of phase 3 of #1095. The scan review no longer treats every reading in
another unit as unwritable. The server tells it which analyte the matched marker
is (markerAnalyteKey on each extracted row); a row whose unit differs but can be
converted starts selected and carries a badge saying what Save will store and
what the report stated ("Saved as 100.9 mg/dL, converted from 5.6 mmol/L"). A
row that cannot be converted keeps the existing blocked badge and error. Save
still sends what the report printed; the server converts, as in slice 2.

The review's duplicate flag also recognises a re-scan of a reading that was
stored converted, by what the report printed, the same rule the commit applies.

A converted reading carries a quiet "converted from 5.6 mmol/L" on the lab list
(row and tile) and the history list (phone and table), so a number nobody typed
can always be traced back to what the report printed.

Strings in all seven locales.

Refs #1095
2026-10-11 20:41:08 +02:00
Marc-André Bombeck 765dbe1e7f Merge branch 'v1422/caption' into release/v1.42.2 2026-10-11 14:41:28 +02:00
Marc-André Bombeck 2f780df0b0 Merge branch 'v1422/autotaken' into release/v1.42.2 2026-10-11 14:41:28 +02:00
Marc-André Bombeck 9a86a9427b fix(oura): name the issuer refusal on the integrations page 2026-10-11 13:59:05 +02:00
Marc-André Bombeck 3c6150e837 fix(admin): sum today's AI spend on each account's own local day 2026-10-11 13:50:17 +02:00
Marc-André Bombeck c94e109bf0 feat(medications): record scheduled doses automatically 2026-10-11 13:46:16 +02:00
Marc-André Bombeck b7eef0dff4 feat(charts): drop the explanatory line under day-linked charts 2026-10-11 13:39:20 +02:00
Marc-André Bombeck 3c4e053dcd Merge branch 'v1422/fixes' into release/v1.42.2 2026-10-11 13:28:29 +02:00
Marc-André Bombeck dcb7a0bc09 fix(ai): count the daily AI budget on the account's own day
The token ledger keyed every day on UTC while the daily briefing and the
other per-day generations run on the account's local day, so east of UTC
the first generations after local midnight were refused against the
previous day's spent ceiling. The budget day is now the calendar day in
the account's time zone; each request still resolves it once and books
its reservation and reconcile on the same row. The medication extraction
reads relative phrases against the same local day, the operator's spend
card shows the operator's own day, and the limit copy says the budget
resets at midnight in the person's time zone.
2026-10-11 13:09:12 +02:00
Marc-André Bombeck 334cb4e979 Merge branch 'v1422/search' into release/v1.42.2 2026-10-11 13:06:07 +02:00
Marc-André Bombeck 1644acf443 feat(palette): list hits from the record under the local results 2026-10-11 12:39:54 +02:00
Marc-André Bombeck 12a8ab7c63 feat(documents): open a PDF or image original in a new browser tab
The document sheet gains an Open in new tab action for the types the
browser renders itself (PDF, JPEG, PNG, WebP, GIF), so a long report
gets the browser's own zoom and search instead of the small preview. It
opens the object URL the sheet already fetched through the app transport:
a plain navigation to the serve route carries no record-session
assertion and would be refused inside a shared record. Every other type
keeps the download only, and the serve route's matrix now pins SVG and
HTML to attachment as well.
2026-10-11 12:37:57 +02:00
Marc-André Bombeck 40e66bf027 feat(notifications): add the content detail preference and the morning score 2026-10-11 12:27:53 +02:00
Marc-André Bombeck 39fc4e4da2 feat(shell): run the docked strips the full height and make them the only fold
The docked panels' strips now run from the top edge of the window to the
bottom, and the top bar ends left of them. The panel header no longer
carries a fold button in docked mode: the strip opens and closes the day
and, on /coach, the conversations; opening moves focus to the panel's
heading and closing returns it to the strip. The sheets keep a close
button, the day's now an X at the end of its header.

The command palette's door is a magnifier at every width, named Search,
with the shortcut in its tooltip. g p opens or closes the day like a
click on its strip, and below the docking width opens the sheet on the
last day or closes it; the shortcuts list shows it under Day.
2026-10-10 20:04:19 +02:00
Marc-André Bombeck 018841e6d6 Merge the final display polish into release/v1.42.0 2026-10-09 17:25:50 +02:00
Marc-André Bombeck dcfec1f35d Merge the final display polish into release/v1.42.0 2026-10-09 17:25:35 +02:00