Commit Graph
8010 Commits
Author SHA1 Message Date
Marc-André Bombeck 7ee72d0161 fix(search): admit the search POST at read level through a declared, frozen readOverPost 2026-10-11 14:21:56 +02:00
Marc-André Bombeck 1bf6108b37 docs(search): describe the command palette's record search 2026-10-11 14:00:31 +02:00
Marc-André Bombeck 3e2426187c test(checkups): pin that a linked visit older than the list's newest hundred is read and opened 2026-10-11 13:59:59 +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 5d7e0248b6 fix(search): probe one row past each cap so a source holding exactly the cap is not reported truncated 2026-10-11 13:57:43 +02:00
Marc-André Bombeck 41049b3837 fix(search): bound the clinical kinds by the search budget, one search per actor, query in a POST body 2026-10-11 13:56:24 +02:00
Marc-André Bombeck 138792d555 docs(db): correct the build cost note on the noted-readings index migration 2026-10-11 13:50:30 +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 5dbc6fcec1 fix(notifications): keep a quick answer single-use after its entry is purged and document the topic exposure 2026-10-11 13:46:12 +02:00
Marc-André Bombeck 4ff9aa7e39 fix(notifications): publish ntfy messages as JSON so non-ASCII labels need no header encoding 2026-10-11 13:43:35 +02:00
Marc-André Bombeck bc91a542e2 fix(google-health): count backfill progress only once it is persisted and cap the slice chain 2026-10-11 13:41:53 +02:00
Marc-André Bombeck a4a3318de3 fix(mood): open the reminder's entry sheet only in the own record 2026-10-11 13:37:46 +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 7a43131883 fix(db): track the time-zone pin's failure log as background work
The pin's SET on connect runs detached; its failure line now registers
with the background-task tracker like every other detached writer. The
coach thread test reads the new budget reset copy.
2026-10-11 13:18:08 +02:00
Marc-André Bombeck 576ff9a444 test(documents): pin that Open in new tab hands over the preview's bytes 2026-10-11 13:15:02 +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 7d8ff0f2df fix(day): keep Escape in the date calendar from closing the whole day
On a phone the date's calendar is a sheet over the day's own sheet. In
the moment after it opens, before Radix has re-rendered both layers, the
day's sheet still holds the Escape listener, so an Escape aimed at the
calendar closed the day as well; the day-view spec caught it as a flake
on the phone viewport (4 of 10 runs locally). The day's sheet now ignores
an Escape that comes from inside another dialog, and the spec waits for
the layer handover instead of racing it.

The coach open-at-end spec read the thread's height as soon as an element
with the thread's slot was visible, but the empty state carries the same
slot. It now waits for the loaded thread's frame and all of its answers.
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 a36e414895 feat(search): widen the clinical read for the in-app search and cover the palette end to end 2026-10-11 12:59:51 +02:00
Marc-André Bombeck 118494b91d test(rollups): stop the summary parity tests going red after midnight UTC
The two summary tests seeded readings counting back from the current
instant, a few more minutes earlier each, and compared the composed mean
with a plain AVG. Between midnight and about 01:15 UTC the earliest
minutes slid into the day before, a day gained a reading in another hour,
and for pulse, whose day is a mean of hourly means, the composed mean
left the plain AVG. The fixtures now count back from noon UTC yesterday,
and the expected mean is the one each type documents: AVG, or the mean
of hourly-mean days.
2026-10-11 12:54:37 +02:00
Marc-André Bombeck 11c55cc6f8 Merge branch 'v1422/notify' into release/v1.42.2 2026-10-11 12:47:15 +02:00
Marc-André Bombeck 8f99b81f5f test(logging): scrub the notification action token from logged paths 2026-10-11 12:46:43 +02:00
Marc-André Bombeck 274cf4900e test(notifications): pin the content preference in backups and the action error codes 2026-10-11 12:46:12 +02:00
Marc-André Bombeck 1b5225ba36 test(search): name the scan-cap mutation as it was run 2026-10-11 12:43:22 +02:00
Marc-André Bombeck 2dc313980b fix(google-health): let a progressing backfill slice end quietly and continue
Since the backfill resumes per collection, a slice that ends before the
whole history is in threw "backfill incomplete" so pg-boss retried it,
which logged job.run.failed at error and grew the queue's failure count
although nothing had failed. A slice that finished at least one more
collection now queues the next slice on the admission queue under its
own singleton key and completes. Only a slice that finished nothing new
still throws, so a backfill that is actually stuck keeps its error. The
import lock keys on the import identity without the slice number, and a
slice that finds the import already stamped walks nothing.
2026-10-11 12:42:58 +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 fca1260b20 fix(oura): exchange and refresh tokens at Oura's current token endpoint
Apps from Oura's current developer portal receive codes from
moi.ouraring.com, and the documented api.ouraring.com/oauth/token answers
those codes with 400 invalid_request, so connecting failed and every
collection read came back 401. Token requests now go to
moi.ouraring.com/oauth/v2/ext/oauth-token first. A code works once, so the
documented endpoint is never asked first: a code whose callback names the
current server goes nowhere else, and only an older app's code or refresh
token gets one retry there after a 400, 401 or 404. The callback checks the
RFC 9207 iss parameter when present and refuses a foreign issuer.
2026-10-11 12:34:33 +02:00
Marc-André Bombeck 5435890275 test(notifications): cover tap targets, quick-answer tokens and the action route; document them 2026-10-11 12:33:02 +02:00
Marc-André Bombeck f65d25b0d0 fix(db): read the clock as UTC in raw SQL and prove it on a Berlin database
Every raw-SQL clock read against a timestamp column without a zone now
writes NOW() AT TIME ZONE 'UTC', so passkey and login challenges, rate
limits, provider pauses, coach usage stamps, tombstone and measurement
windows no longer pass through the session time zone even where the
per-connection pin cannot apply. The regression-window bounds stay naive
UTC timestamps instead of being turned into timestamptz. A structural
guard keeps bare NOW() / CURRENT_TIMESTAMP out of raw SQL outside a short
list of timestamptz targets. The integration test sets the database
default to Europe/Berlin and drives challenge claims, session expiry, the
native sign-in handoff freshness check and the rate-limit window through
the app's client, plus the challenge claim through an unpinned client.
Self-hosting docs describe the pin for an existing or shared Postgres.
2026-10-11 12:31:37 +02:00
Marc-André Bombeck 9b86ec2e10 test(search): cover the matcher, the scan bounds and the route 2026-10-11 12:29:41 +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 1766ffa3d2 feat(search): search the record from one endpoint 2026-10-11 12:27:28 +02:00
Marc-André Bombeck f19dfc4572 feat(notifications): resolve a tap target per event and offer mood quick answers 2026-10-11 12:21:51 +02:00
Marc-André Bombeck 42ba471765 refactor(search): share the record matcher and give record candidates display data 2026-10-11 12:20:15 +02:00
Marc-André Bombeck cefc8c15c1 fix(db): pin every connection to UTC and say so at boot when it is not
Stored times are UTC in timestamp columns without a zone, and Postgres
reads now(), CURRENT_TIMESTAMP and offset-free timestamptz parameters
through the session time zone. On a database whose default is not UTC
every expiry check ran off by the offset. The Prisma pool, pg-boss, the
lock and the maintenance connections now send TimeZone=UTC as a startup
option, or SET it on connect when the startup options are disabled for
a pooler. A boot check reads SHOW TimeZone and warns on anything else.
2026-10-11 12:15:03 +02:00
Marc-André Bombeck 9aadb29876 Merge pull request #1199 from MBombeck/feat/strip-full-height
feat(shell): full-height docked strips, magnifier search, g p for the day
2026-10-10 20:42:22 +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 023115b05c fix(timeline): keep each mean's dot and value one unbreakable unit
The dot before a mean sat on the x-height middle, a little below the
text, and a wrapping line could leave it at the end of one line while its
value moved to the next. Each dot and value is now one inline-flex unit
that centres the dot on the text line and never wraps inside; the row
breaks only between units, a long name is cut short inside its own unit,
and the leading mean sign rides in the first unit. The legend and chip
dots no longer shrink beside long text.
2026-10-10 20:04:13 +02:00
Marc-André Bombeck b787bc3176 Merge pull request #1198 from MBombeck/release/v1.42.1
Release v1.42.1
v1.42.1
2026-10-10 14:18:23 +02:00
Marc-André Bombeck 099ea514b1 chore(release): v1.42.1 2026-10-10 13:56:41 +02:00
Marc-André Bombeck 1afe0ee2e4 Merge pull request #1197 from MBombeck/fix/dashboard-top-card-gap
Keeps the gap under the dashboard's top card.
2026-10-10 13:54:47 +02:00
Marc-André Bombeck 020663d1f7 Merge branch 'main' into fix/dashboard-top-card-gap 2026-10-10 13:30:02 +02:00
Marc-André Bombeck 3ad82590c6 Merge pull request #1196 from MBombeck/fix/google-health-1194-1195
Refs #1194, #1195
2026-10-10 13:29:59 +02:00
Marc-André Bombeck 01aa4e5ba1 fix(dashboard): keep the gap under the top card 2026-10-10 13:21:59 +02:00
Marc-André Bombeck 46047e57c0 fix(google-health): keep long backfills out of reauth parking and settle overlapping sleep segments
A history backfill carried one access token through walks that outlive it.
After an hour every request answered 401, which classifies as a revoked
grant, so the account was parked at error_reauth with a refresh token that
was still valid, and every later run skipped it until a manual reconnect.
Running beside the hourly sync, the backfill also pushed the account over
Google's per-minute quota, and each 429 failed its whole collection.

- Walks take a token source that renews the access token before it expires
  and once more when Google refuses it mid-walk.
- A 429 is waited out (Retry-After, RetryInfo, else a doubling backoff) and
  the request repeated; it is never a reauth.
- error_reauth only short-circuits a run when the token endpoint refused the
  grant (needsReauth). A connection parked by a data request's 401 refreshes
  on its next run and clears itself when that run completes.
- One run per account at a time: syncs, the backfill and the sleep repair
  share an advisory lock. The hourly poll skips a held account, a manual
  sync answers 409 sync_in_progress, the backfill waits a bounded time.
- A backfill attempt records each collection it finishes cleanly
  (backfill_progress) and the next attempt resumes with the rest.
- The incremental watermark is stamped with the cycle's start, not its end.

Overlapping sleep segments that share a stage and an end share the natural
key (type, measuredAt, source, sleepStage). A re-score that moved one row
onto a sibling's slot threw P2002 and failed the sync on every run.

- A batch keeps one reading per natural key, chosen the same way each time
  (longer segment, then smaller externalId).
- A move that still collides is settled by reconcileExternalMeasurement,
  which retires the stale row, instead of failing the sync.
- Updates run before inserts, and the key-format rescue no longer re-keys a
  row this batch is moving.
- The sleep replace-by-window protects every session's fresh rows, so two
  overlapping sessions no longer tombstone and resurrect each other hourly.

Refs #1194, #1195
2026-10-10 12:59:25 +02:00
Marc-André Bombeck f0b4e902bb Merge pull request #1193 from MBombeck/fix/maintenance-shm
Refs #1192
2026-10-10 12:19:02 +02:00
Marc-André Bombeck a2ee79a746 fix(maintenance): run the measurement vacuum without a /dev/shm segment 2026-10-10 09:33:17 +02:00
dependabot[bot] e1eebebd1d chore(deps-dev): bump the development-weekly group across 1 directory with 3 updates (#1191)
Bumps the development-weekly group with 3 updates in the / directory: [@next/bundle-analyzer](https://github.com/vercel/next.js/tree/HEAD/packages/next-bundle-analyzer), [lefthook](https://github.com/evilmartians/lefthook) and [shadcn](https://github.com/shadcn-ui/ui/tree/HEAD/packages/shadcn).


Updates `@next/bundle-analyzer` from 16.3.3 to 16.3.8
- [Release notes](https://github.com/vercel/next.js/releases)
- [Commits](https://github.com/vercel/next.js/commits/v16.3.8/packages/next-bundle-analyzer)

Updates `lefthook` from 2.2.1 to 2.1.17
- [Release notes](https://github.com/evilmartians/lefthook/releases)
- [Changelog](https://github.com/evilmartians/lefthook/blob/master/CHANGELOG.md)
- [Commits](https://github.com/evilmartians/lefthook/compare/v2.2.1...v2.1.17)

Updates `shadcn` from 4.21.4 to 4.21.3
- [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.21.3/packages/shadcn)

---
updated-dependencies:
- dependency-name: "@next/bundle-analyzer"
  dependency-version: 16.3.8
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: development-weekly
- dependency-name: lefthook
  dependency-version: 2.1.17
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: development-weekly
- dependency-name: shadcn
  dependency-version: 4.21.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: development-weekly
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-10 02:07:07 +00:00
Marc-André Bombeck b10a1132e6 Merge pull request #1190 from MBombeck/deps/vitest-5
chore(deps): vitest 5
2026-10-10 03:37:09 +02:00