Commit Graph
6524 Commits
Author SHA1 Message Date
Marc-André Bombeck 76d80fbed4 test(e2e): pass an unswitched auth payload through the corrupting route
The malformed-payload journey installs its /api/auth/me route before it
clicks the switch. When the owner session read its own payload again in
that window, the helper threw inside the route handler: the throw came
before fulfill, so its catch never saw it, the test failed, and the
teardown's unroute then hit a closed page. It showed up on the Playwright
1.63 branch, whose timing opens that window more often. An unswitched
payload now passes through unchanged, and the test asserts that at least
one switched response was actually corrupted before trusting the refusal.
2026-09-13 22:20:15 +02:00
Marc-André Bombeck 66b0dbb67b Merge pull request #968 from MBombeck/dependabot/npm_and_yarn/prisma-7.10.0
chore(deps): bump prisma from 7.8.0 to 7.10.0
2026-09-13 22:18:21 +02:00
Marc-André Bombeck 0ddf8de9bf Merge main into the Prisma 7.10 update 2026-09-13 21:17:11 +02:00
Marc-André Bombeck c3871289ee Merge pull request #973 from MBombeck/fix/e2e-session-call-origin
test(e2e): give an unnavigated page an origin before a session call
2026-09-13 21:17:08 +02:00
Marc-André Bombeck 99ddf0db5d test(e2e): give an unnavigated page an origin before a session call
The setup flow specs answer questions through these helpers before their
first real navigation. That case still went through page.request, which
shares the runner's keep-alive agent, and a stale socket failed an answer
with read ECONNRESET on the dependency update branches. The page now opens
the public version endpoint first and sends the call with its own fetch.
2026-09-13 20:58:04 +02:00
Marc-André Bombeck 7787a5cf5e Merge main into the Prisma 7.10 update 2026-09-13 20:33:18 +02:00
Marc-André Bombeck 36ff3e7cb9 chore(deps): move the Prisma client and the image CLI to 7.10
The bump raised the CLI to 7.10.0 but left @prisma/client at 7.8.0 and
the migration CLI the image installs under /opt/prisma-cli at 7.8.0, so
the generated client, the one that ships and the one that migrates would
have come from two releases. All three are 7.10.0 now.
2026-09-13 20:33:17 +02:00
Marc-André Bombeck b794a256d0 Merge pull request #970 from MBombeck/dependabot/npm_and_yarn/pdfjs-dist-6.3.289
chore(deps-dev): bump pdfjs-dist from 6.2.108 to 6.3.289
2026-09-13 20:22:08 +02:00
dependabot[bot] a5b5faec83 chore(deps): bump prisma from 7.8.0 to 7.10.0
Bumps [prisma](https://github.com/prisma/prisma-cli/tree/HEAD/packages/prisma) from 7.8.0 to 7.10.0.
- [Release notes](https://github.com/prisma/prisma-cli/releases)
- [Commits](https://github.com/prisma/prisma-cli/commits/HEAD/packages/prisma)

---
updated-dependencies:
- dependency-name: prisma
  dependency-version: 7.10.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-09-13 17:50:31 +00:00
dependabot[bot] 2d92c16729 chore(deps-dev): bump pdfjs-dist from 6.2.108 to 6.3.289
Bumps [pdfjs-dist](https://github.com/mozilla/pdf.js) from 6.2.108 to 6.3.289.
- [Release notes](https://github.com/mozilla/pdf.js/releases)
- [Commits](https://github.com/mozilla/pdf.js/compare/v6.2.108...v6.3.289)

---
updated-dependencies:
- dependency-name: pdfjs-dist
  dependency-version: 6.3.289
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-09-13 17:48:39 +00:00
Marc-André Bombeck 9e81369279 Merge pull request #965 from MBombeck/dependabot/npm_and_yarn/vitejs/plugin-react-6.1.1
chore(deps-dev): bump @vitejs/plugin-react from 6.1.0 to 6.1.1
2026-09-13 19:42:21 +02:00
Marc-André Bombeck 2ad84c97d4 Merge pull request #969 from MBombeck/dependabot/github_actions/pnpm/action-setup-6.1.0
chore(deps): bump pnpm/action-setup from 6.0.10 to 6.1.0
2026-09-13 19:42:18 +02:00
Marc-André Bombeck 2f1dadabb9 Merge pull request #967 from MBombeck/dependabot/github_actions/codeql-action-8213001b74
chore(deps): bump the codeql-action group with 3 updates
2026-09-13 19:42:15 +02:00
Marc-André Bombeck 293ddcb3ee Merge pull request #971 from MBombeck/release/v1.38.22
Release v1.38.22
v1.38.22
2026-09-13 19:10:26 +02:00
Marc-André Bombeck f293d31850 test(e2e): send the setup flow calls over the page's own connection
The setup flow helpers read the account, the dashboard layout and wrote
answers through page.request, which shares the runner's keep-alive agent
with every other API context. A socket the server had already closed on
its idle timeout failed one answer with read ECONNRESET, and CI counts
the passing retry as a failure. The calls go through the page's fetch
now, as the record session specs already do; before the first navigation
there is no origin, so that case keeps the API context.
2026-09-13 18:54:54 +02:00
Marc-André Bombeck 2207bb1114 chore(release): v1.38.22 — a channel test waits until you save 2026-09-13 18:28:47 +02:00
Marc-André Bombeck 3bb08c3c8a fix(settings): hold the channel test until changes are saved
The webhook, ntfy, email and Telegram test routes send through the
saved channel config. After a field changed, the card kept showing the
Saved note from the last save and Test still ran, so it reported on the
old settings: a webhook switched to the Gotify format was tested with
the generic body and Gotify refused it. The note now disappears on a
change, and the test button stays off with a save-first hint while the
form differs from what is saved. Refs #947
2026-09-13 18:28:47 +02:00
dependabot[bot] 6fb7a3835f chore(deps): bump pnpm/action-setup from 6.0.10 to 6.1.0
Bumps [pnpm/action-setup](https://github.com/pnpm/action-setup) from 6.0.10 to 6.1.0.
- [Release notes](https://github.com/pnpm/action-setup/releases)
- [Commits](https://github.com/pnpm/action-setup/compare/0977fd99725f1db4007ccb2928dbb4e90d06cc86...ea17c68df8912ef543352723c149a84f56e3d413)

---
updated-dependencies:
- dependency-name: pnpm/action-setup
  dependency-version: 6.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-09-13 15:55:28 +00:00
dependabot[bot] 52c1da6034 chore(deps): bump the codeql-action group with 3 updates
Bumps the codeql-action group with 3 updates: [github/codeql-action/init](https://github.com/github/codeql-action), [github/codeql-action/analyze](https://github.com/github/codeql-action) and [github/codeql-action/upload-sarif](https://github.com/github/codeql-action).


Updates `github/codeql-action/init` from 4.37.9 to 4.38.0
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/cdf488f595d80d6e07e03d4674febd5ab45fa938...b96794f015dfd88f77b49b1c93e0fa7110f94c63)

Updates `github/codeql-action/analyze` from 4.37.9 to 4.38.0
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/cdf488f595d80d6e07e03d4674febd5ab45fa938...b96794f015dfd88f77b49b1c93e0fa7110f94c63)

Updates `github/codeql-action/upload-sarif` from 4.37.9 to 4.38.0
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/cdf488f595d80d6e07e03d4674febd5ab45fa938...b96794f015dfd88f77b49b1c93e0fa7110f94c63)

---
updated-dependencies:
- dependency-name: github/codeql-action/init
  dependency-version: 4.38.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: codeql-action
- dependency-name: github/codeql-action/analyze
  dependency-version: 4.38.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: codeql-action
- dependency-name: github/codeql-action/upload-sarif
  dependency-version: 4.38.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: codeql-action
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-09-13 15:54:49 +00:00
dependabot[bot] 530d2849bb chore(deps-dev): bump @vitejs/plugin-react from 6.1.0 to 6.1.1
Bumps [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react) from 6.1.0 to 6.1.1.
- [Release notes](https://github.com/vitejs/vite-plugin-react/releases)
- [Changelog](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite-plugin-react/commits/plugin-react@6.1.1/packages/plugin-react)

---
updated-dependencies:
- dependency-name: "@vitejs/plugin-react"
  dependency-version: 6.1.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-09-13 15:53:54 +00:00
Marc-André Bombeck d4766a580b Merge pull request #963 from MBombeck/release/v1.38.21
Release v1.38.21
v1.38.21
2026-09-13 15:38:09 +02:00
Marc-André Bombeck 8c8e03a6eb chore(release): v1.38.21 — channel tests say why they failed, and Gotify gets its format 2026-09-13 15:18:20 +02:00
Marc-André Bombeck 669058d37c Merge the review fixes for channel tests 2026-09-13 15:17:36 +02:00
Marc-André Bombeck 3dece61cc8 Merge the review fix for record settings the grant cannot manage 2026-09-13 15:17:36 +02:00
Marc-André Bombeck d4fa7d5913 Merge the review fixes for the service worker and the Loki note 2026-09-13 15:17:36 +02:00
Marc-André Bombeck 60dfffc7ad docs(api): name each channel's own credentials in test errors
The ntfy and webhook 502 descriptions shared one list of refused credentials that neither channel fully has. Each now names its own, including the userinfo and long path segments of a webhook URL. The email description names the TLS, protocol and envelope cases.

Refs #947
2026-09-13 14:50:33 +02:00
Marc-André Bombeck 32eaf7a29e fix(admin): show each channel's cause in the notification test toast
The admin test response carried a code and status per channel that nothing rendered. The toast now lists each failing channel with the translated cause and the HTTP status or SMTP code. The relay reply is no longer part of that response, and the ntfy error no longer echoes the topic, which the sender treats as a secret.

Refs #947
2026-09-13 14:50:33 +02:00
Marc-André Bombeck 2480c9fa55 fix(notifications): refuse encoded and path-borne secrets in replies
Userinfo and each query value are decoded on their own, so one malformed escape no longer discards every other secret in the URL. A reply is compared with each secret in literal, JSON-escaped and percent-encoded form, and URL path segments of 16 or more characters count as secrets, which covers the token in a Discord or Slack webhook URL and an n8n webhook id.

Refs #947
2026-09-13 14:50:33 +02:00
Marc-André Bombeck f81cdf8768 fix(notifications): name TLS, protocol and envelope faults in email tests
A STARTTLS failure (port 465 set up as 587) and a protocol error now read as connection_failed, and an envelope or message refused without a reply code as upstream_rejected. They used to fall through to the 500 for an unnamed failure.

Refs #947
2026-09-13 14:50:33 +02:00
Marc-André Bombeck a11e5991cf test(settings): read a real failure response through the test button
The fetch and envelope reading move into runConnectionTest, which the button calls. A test stubs the fetch with the 502 envelopes the notification test routes send and asserts the rendered code, HTTP status, SMTP code and relay reply, so dropping the meta extraction fails it.

Refs #947
2026-09-13 14:50:32 +02:00
Marc-André Bombeck 6a663dfc27 fix(notifications): record a relay refusal at warn, not error
A 502 from a channel test reports the user's relay or mail setup, not a fault on this server, yet the status alone raised every press to an error-level event. The event builder gains a ceiling for the status-derived level, and the test routes cap it at warn on the 502 path. The 500 for an unnamed failure stays at error, and explicit elevations are unaffected.

The notifications guide notes that a reverse proxy which replaces 5xx pages hides the detail, so the card falls back to Test failed.

Refs #947
2026-09-13 14:50:32 +02:00
Marc-André Bombeck 45ee70acb7 fix(settings): list record content only where the grant manages it
The anamnesis page writes through requireRecordAuth("manage",
"profile"), which refuses a grant whose sections do not reach profile.
The Settings list and the navigation entry checked only the level and
the record kind, so a MANAGE grant scoped away from profile would be
offered a page whose saves are refused.

Record-content destinations now name the section they write, and are
listed only when the active record's manageable sections include it.
A destination without a named section is never listed. The shell and
the navigation read the same predicate. MANAGE grants are whole-record
today, so managed profiles and adult MANAGE shares list what they did
before.

Refs #939
2026-09-13 14:49:56 +02:00
Marc-André Bombeck 873e9cb4fb fix(pwa): keep a subscribed worker registered behind a gateway
A same-origin auth gateway that answers an expired session with a 200
sign-in page returns HTML for both the navigation and the /api/version
probe, which read as another app. The worker then unregistered and
destroyed the Web Push subscription, which nothing re-creates, so
reminders stopped without notice.

The worker no longer unregisters while the registration holds a push
subscription, or when the lookup is unavailable. It deletes its caches
and passes requests to the network for the rest of its life instead.
The probe now sends same-origin credentials, so a valid gateway cookie
reaches HealthLog.

Refs #847
2026-09-13 14:45:31 +02:00
Marc-André Bombeck b1331de130 docs(env): name the unspecified address among refused Loki hosts
The Loki block listed link-local and metadata addresses as the only
refused destinations; 0.0.0.0 and :: are refused too.

Refs #947
2026-09-13 14:45:30 +02:00
Marc-André Bombeck 6b146c25d9 fix(settings): stop telling people the webhook URL must be public
A notification target on a private network has been reachable since the
operator allowlist for private origins arrived; the hint under the URL
field and the guide still said the address had to be public.
2026-09-13 14:31:24 +02:00
Marc-André Bombeck 4306bf1aec Merge channel tests that report the other end's answer, and the Gotify format 2026-09-13 14:30:14 +02:00
Marc-André Bombeck f89dda81a6 test: point the prefix drift guard at the shared matcher
The guard read src/lib/idempotency.ts for the hle_ prefix, which moved to src/lib/secret-shape.ts with the matcher. It now asserts that the shared matcher refuses an hle_ token and that the idempotency cache imports and calls it, so a private copy of the pattern would fail it too.
2026-09-13 14:24:37 +02:00
Marc-André Bombeck e788b53be0 docs(notifications): describe what the webhook sends and Gotify setup
The outbound payload was documented nowhere. The webhook section now shows the generic body and the Gotify body as the Test button sends them, what each field carries, and how to point the webhook at Gotify: a URL ending in /message, the application token in an X-Gotify-Key header, and the Gotify format.

Refs #947
2026-09-13 14:19:48 +02:00
Marc-André Bombeck fafb5cdc08 feat(notifications): add a Gotify payload format to the webhook
Gotify's POST /message types priority as an integer, so the generic body, which sends the word, was refused with a 400 before the token was ever the question. The webhook card now offers a payload format: generic, which stays byte for byte what it was, and gotify, which sends title, message, an integer priority and extras.

Priorities follow the Gotify Android client's channel thresholds: 5 for routine events (audible), 8 for medication reminders (the lowest heads-up value), 10 for urgent events. The extras declare plain text and carry the event name, masked to reminder in discreet mode as the generic body does.

The choice lives in the encrypted channel config, so no migration: an absent format is generic, only gotify is written, and a save that omits the field keeps the stored choice. GET returns the resolved value. The sender comment no longer suggests an Authorization Bearer header for Gotify, which takes X-Gotify-Key or a token query parameter.

Refs #947
2026-09-13 14:19:48 +02:00
Marc-André Bombeck f1aebcc3bf Merge private Loki shipping and the service worker that leaves a foreign origin 2026-09-13 14:17:25 +02:00
Marc-André Bombeck e34c5db45e fix(pwa): confirm a foreign origin before the worker retires
A reverse proxy with a response-header allowlist strips
X-HealthLog-Page from every real HealthLog page, and the worker then
unregistered on each load and dropped Web Push subscriptions.

A successful page without the marker now only sends requests to the
network while the worker asks /api/version with no-store and a manual
redirect. It deletes its caches and unregisters only when the answer
positively is not HealthLog: a 404, a non-JSON 2xx, or JSON without
the version shape. A failed probe, any other status or the HealthLog
shape resumes normal service. buildSha may be null on a self-built
image, so only its presence is checked.

Refs #847
2026-09-13 14:16:52 +02:00
Marc-André Bombeck 92606f6409 feat(settings): show the status and reply of a failed channel test
The test-connection callout now appends the HTTP status or SMTP reply code the route reports, and shows what the relay answered on a line beneath it. The reply is rendered as a React text child, so markup in it is shown as characters.

Adds the upstream_rejected message in all seven locales.

Refs #947
2026-09-13 14:13:55 +02:00
Marc-André Bombeck dd5dd1e45e docs(nav): correct two comments about utilities and manage invites
The More hub carries feature destinations only; Settings and
Notifications sit in the top-bar menu. The browser-only refusal for a
manage invitation comes from the transport check, which runs before and
independently of the second-factor step-up.
2026-09-13 14:12:54 +02:00
Marc-André Bombeck 7d40103616 Merge Settings inside a profile you look after 2026-09-13 14:12:18 +02:00
Marc-André Bombeck f6a890df8a fix(notifications): answer a failed channel test with its cause
The webhook, ntfy and email test routes turned every delivery failure into a bare 500, so the settings card could only say "Test failed" while the server knew the relay had answered 400. A failure at the other end, or on the way to it, is now a 502 with meta.errorCode, the upstream HTTP status or SMTP reply code, and for webhook and ntfy what the relay answered when that is short and holds no credential. The codes reuse the test card's vocabulary; upstream_rejected is new, for a relay that accepted the connection and refused the payload. The private-origin 422 is unchanged, and only a failure the server cannot name stays a 500.

The guard that pinned the bare 500 now asserts the opposite, with the reason in its name.

The admin fan-out test reports the same code and status per channel, and tests the webhook and email channels, which it used to list as an unknown channel type.

Refs #947
2026-09-13 14:10:35 +02:00
Marc-André Bombeck c93a384db8 Merge pull request #933 from MBombeck/dependabot/npm_and_yarn/tanstack/react-query-5.102.8
chore(deps): bump @tanstack/react-query from 5.101.4 to 5.102.8
2026-09-13 14:09:38 +02:00
Marc-André Bombeck 8c345f600e feat(notifications): keep what the relay answered on a failed send
The webhook and ntfy senders now carry up to 200 characters of a non-2xx response body on the send outcome, with control and formatting characters removed. The body is dropped when it looks like a credential or echoes the header value, auth token, topic or a URL token. Nothing stores it; the ledger row and channel state keep the reason code as before.

Transport faults without a status now say whether they were a timeout or a refused connection, and the email sender maps SMTP failures into the same vocabulary with the reply code. Both exist so the test routes can answer with the cause instead of a bare 500.

Refs #947
2026-09-13 14:04:40 +02:00
Marc-André Bombeck 4a49120fcf fix(i18n): say the manage invite asks a second factor only if set
Offering manage access is refused outside a browser session, and the
second factor is asked only when the account has one. The note under
the manage option and the browser-only error said the factor was
always asked. Reworded in all seven locales.
2026-09-13 14:03:21 +02:00
Marc-André Bombeck 60a5783534 test(e2e): walk to a managed profile's Modules settings
Switch into the managed record, follow the sidebar Settings entry to
the profile card and on to the Modules card, then repeat from the
phone-width user menu. Asserts the entry's target, the absent
Notifications entry and the record id on each card, after the shell
has loaded.

Refs #939
2026-09-13 14:03:17 +02:00
Marc-André Bombeck 9dcef3b0e2 fix(nav): offer Settings inside a record that has Settings pages
A self-hoster looking after a managed profile could not find Settings
after switching into it: the utility entries vanished for every shared
record, while the Settings shell lists the profile's own configuration
and the section gate admits it.

The utility tail now answers for the record on screen. Settings is
offered when the shell lists at least one section for it and links to
the first one: the profile card for a managed profile, the anamnesis
page for an adult share at manage. Read and write shares, and a
refused or pending switch, get no utility. Notifications stays hidden
under every switch. The desktop sidebar footer and the mobile user
menu read the same list; the footer identity block stays a plain
block.

Refs #939
2026-09-13 14:03:16 +02:00