5988 Commits
Author SHA1 Message Date
Marc-André Bombeck 72117104d5 Merge pull request #887 from MBombeck/release/v1.38.2
chore(release): v1.38.2 — Anthropic on current models, briefing in your language
v1.38.2
2026-09-02 11:33:55 +02:00
Marc-André Bombeck 56ded00395 chore(release): v1.38.2 — Anthropic on current models, briefing in your language
No assistant prefill on Anthropic JSON calls, Claude 5 and Fable count as
vision-capable, the briefing cache carries its language and is never
served to a reader of another one, and job paths resolve a missing
account language to the instance default.
2026-09-02 11:10:35 +02:00
Marc-André Bombeck ad0a055fdc Merge pull request #886 from MBombeck/fix/briefing-locale
fix: never serve the briefing in another language than the reader's
2026-09-02 11:09:23 +02:00
Marc-André Bombeck a55ecc5a48 Merge origin/main into fix/briefing-locale 2026-09-02 10:51:56 +02:00
Marc-André Bombeck 718cc3568f Merge pull request #885 from MBombeck/fix/anthropic-no-prefill
fix(ai): no assistant prefill on Anthropic, Claude 5 counts as vision-capable
2026-09-02 10:51:25 +02:00
Marc-André Bombeck 7414f6e79b Note the briefing language fix in the changelog 2026-09-02 10:44:04 +02:00
Marc-André Bombeck f003b6f413 Resolve job-side locale through the operator default
Every background path that resolved a user row's locale collapsed a
NULL column to English: the nightly briefing warm, the status crons,
the period-narrative warm, reaction lines, the morning refresh, the
briefing push, coach nudges, the reminder workers, and the document and
workout summaries each carried their own copy of
`locales.includes(x) ? x : defaultLocale` or called
`normalizeLocale(user.locale)`. None consulted the instance's configured
default language, so an account that never touched the language picker
got English prose and English pushes on a German-language instance.

Add resolveJobLocale (src/lib/i18n/job-locale.ts): stored user locale
when valid, else the operator's app_settings.default_locale when valid,
else English. The settings read lives beside the other app-settings
accessors. Every job and daily path resolves through it once, where it
has the row; the template helpers keep coerceLocale for a value that is
already resolved, and queue payloads keep normalizeLocale.

The briefing push hands its resolved locale down to the digest, and the
digest to the snapshot read, so the push copy and the digest lines are
in the same language instead of two different fallbacks.

A structural test walks src/lib/jobs and src/lib/daily and fails on a
hand-rolled coercion, a validator applied to a row column, or a row
reader that does not import the helper. It was red against the previous
tree on all three counts.
2026-09-02 10:44:04 +02:00
Marc-André Bombeck ba4e34f09e Tag the briefing cache with its language and refuse a foreign one
The comprehensive-briefing cache (User.insightsCachedText) is one slot
per account with no record of the language it was written in. Every
reader served whatever was there, so a German-language account whose
nightly warm had written English kept seeing English on the dashboard
lead and the Today briefing. The request path only replaced it once the
row was a day old and the provider answered, which with a provider at
its usage limit was never.

Add User.insightsCachedLocale (migration 0335). Both writers store the
locale they generated in; the timestamp-only refresh on an unchanged
snapshot tags the row too, since the fingerprint covers the generation
locale. Every reset that nulls the text nulls the tag.

The snapshot briefing lift and GET /api/insights/generate treat a tag
that differs from the reader's locale as an empty cache: no prose, no
timestamp, the preparing / no-provider state, and the out-of-band warm
enqueued in the reader's locale through the existing path. The
generator's own short-circuit and the POST short-circuit refuse to call
a foreign-language row fresh. A NULL tag (rows written before this
change) is served as before until the next write tags it. The Today
digest derives from the snapshot and follows.

Covered by unit tests on the lift, the route and the generator, and an
integration test that writes the row through Prisma and reads the
snapshot for a reader in another language.
2026-09-02 10:44:03 +02:00
Marc-André Bombeck 7d93af9d09 fix(ai): recognise Claude 5 and Fable models as vision-capable
The Anthropic vision check listed the Claude 3 and 4 families by prefix,
so a key pinned to claude-sonnet-5, claude-opus-5 or a Fable model was
told the provider cannot read images, and lab and document OCR refused
the upload even though the model handles image and PDF blocks.

Replace the per-release prefix list with a rule: any claude-<tier>-<major>
slug from the 4 family upward, plus every claude-fable-* model, counts as
vision-capable. Claude 3 handling is unchanged. The Settings preset list
gains claude-sonnet-5 and claude-opus-5 alongside the existing entries.
2026-09-02 10:32:50 +02:00
Marc-André Bombeck a463206774 fix(ai): stop prefilling the assistant turn on Anthropic JSON calls
The Anthropic client steered JSON replies by appending an assistant turn
containing an opening brace and gluing the brace back onto the reply.
Current Claude models (the 4.6 / 4.7 / 4.8 family, Opus 5, Sonnet 5,
Fable 5 and 5.1) reject an assistant prefill with HTTP 400, so every
JSON surface on the provider (briefing, status cards, document and lab
extraction) failed for a self-hoster on a current model while plain chat
kept working.

Drop the prefill on every model. The request now carries a plain
instruction on the last user turn to reply with a single JSON object and
nothing else, and the reply is narrowed to the outermost object body via
a shared extractJsonObject helper, so a fenced or prefixed answer still
parses. The insights stripJsonFences helper delegates to the same
function rather than keeping a second copy. The tool-use path is
unchanged.

Reported independently by @sweidinger.
2026-09-02 10:28:05 +02:00
Marc-André Bombeck d5cf82fb6e Merge pull request #884 from MBombeck/release/v1.38.1
chore(release): v1.38.1 — push readings in, see the range at a glance
v1.38.1
2026-09-01 21:26:13 +02:00
Marc-André Bombeck a2e50c761f Note the callback-notice fix and the mysql2 pin in the changelog 2026-09-01 21:00:50 +02:00
Marc-André Bombeck 05d3736d75 Resolve OAuth callback URLs on the server for integration cards
The v1.38.0 notice that warns when the configured OAuth callback origin
differs from the origin the browser is on never rendered in the published
image, and the copyable callback address in the redirect guide showed a
bare path. `integrationCallbackUrl()` read `process.env.NEXT_PUBLIC_APP_URL`
inside a "use client" module. Next.js inlines NEXT_PUBLIC_* into client
bundles at build time, and the GHCR image is built without that variable
(only the version, build-sha and built-at args reach the build), so the
base compiled to an empty string, `new URL("/api/<provider>/callback")`
threw, and the notice returned null on every card for every self-hoster.

The value now comes from the server at request time. A new map
(`src/lib/integrations/callback-urls.ts`) calls each provider's own
redirect-URI function (the four private `getRedirectUri()` helpers are
exported under provider-specific names; Polar, Oura and Strava already
exported theirs), so the page shows exactly what the handshake registers,
explicit `*_REDIRECT_URI` override included. The settings route resolves
the map and passes it as a prop through `IntegrationsSection` and
`ConnectionsPanel` to every card. Fitbit and Google Health validate their
URI and throw on a bad configuration; that surfaces as `null`, the notice
skips the comparison and the guide falls back to the fixed path.

Tests: a map test proving the explicit override wins and the derived form
is used otherwise, a component test rendering the notice from a passed
value (mismatch renders, match does not), and a structural guard that
fails when any "use client" file under src/components/settings/integrations
reads NEXT_PUBLIC_APP_URL.
2026-09-01 21:00:12 +02:00
Marc-André Bombeck 97b1603cb9 Pin mysql2 past GHSA-3f6p-5ww8-9rcr in both installs
The dependency audit went red on the release branch: mysql2 below 3.22.0
downgrades its auth plugin to mysql_clear_password and leaks the
credential. It reaches the tree only through prisma's MySQL driver, which
this app never opens, but the gate does not distinguish reachable from
present. Pinned to ^3.22.0 in the workspace overrides and mirrored with
npm's own override for the /opt/prisma-cli install, the pair the
lockstep guard holds together. The audit reads three moderates, below
the gate.
2026-09-01 20:53:47 +02:00
Marc-André Bombeck c462d9a282 chore(release): v1.38.1 — push readings in, see the range at a glance
A measurement ingest token for readings from your own hardware, a
reference-range bar beside every lab reading, lab OCR working with a
GPT-5 model, an impossible reference window no longer written to the
record, and the image build kept intact across the Prisma adapter bump.
Dependency updates ride along.
2026-09-01 20:33:30 +02:00
Marc-André Bombeck cba389515c ci: split the integration suite four ways and widen the guard
Three of the last four pushes to main failed the integration workflow
without a single failing test. Shard 1 of 3 was still logging green
results when the 25-minute job timeout cancelled it; the same tests in
the same shard had run in 13 minutes the day before. A slow runner day
doubles every test's wall time, and a guard under twice the ordinary
run cannot absorb that.

Four shards keep each slice around fifty files, and the guard moves to
40 minutes, three times an ordinary run. A wedged test still fails
through vitest's own 60-second budget, so the job timeout only has to
catch a container that never boots. The fan-in job is unchanged; it
still refuses a matrix with any cancelled shard.
2026-09-01 20:28:32 +02:00
Marc-André Bombeck 8016d375c6 Merge pull request #880 from TimonBed/lab-visual-improvement
Improve lab range and trend visual alignment
2026-09-01 19:06:09 +02:00
Marc-André Bombeck 60939475b4 Give an impossible reference window no verdict at all
A floor at or above its ceiling fell through to the one-sided branch and
was read as "minimum only", which paints a high reading green. That is
the wrong direction for a transcription error to fail in: the colour
answers a question nobody could answer from that data.

Each one-sided branch now requires the OTHER bound to be absent, so a
present-but-impossible pair lands on the neutral dot instead. It matches
lab-reference-range-bar.tsx, which renders nothing for the same input —
the two components sitting next to each other should not disagree about
what a nonsense range means.

The file had no test. It has one now, covering all five window shapes
plus the zero-width band; with the two conditions relaxed again, exactly
the two new cases fail and the four existing ones stay green.
2026-09-01 18:51:07 +02:00
Marc-André Bombeck 1cc5779282 Merge pull request #883 from MBombeck/docs/knip-triage-current
Say which knip entry is kept on purpose, and re-measure the count
2026-08-31 21:43:05 +02:00
Marc-André Bombeck 6d98a67751 Say which knip entry is kept on purpose, and re-measure the count
The production pass reports 22 files, and the comment said 21 — a small
drift, but the paragraph reads as a triage nobody has redone, so the
number is dated now and carries an instruction to re-measure.

Two things the block did not say:

The standing exception. `signals/adapters/metric-status.ts` is reported
unreachable because its only importer is its own registry-invariant test.
That is what the module is for: it projects the signal registry onto the
MetricStatusMeta shape so the test can assert the two agree field for
field. Deleting it to clear the line removes a check rather than ballast.
Someone triaging the list without that written down has to rediscover it,
and the obvious move is the wrong one.

The healed example. The false-positive slot cited a module reported
because scripts/ sits outside the tsconfig that defines the @/ alias.
It no longer appears — module and importing script both still exist, so
resolution improved under us. Replaced with the case that does hold
today, the service-worker policy that public/sw.js mirrors by hand, and
the old one kept as a note: an example that heals silently makes the
reasoning around it look wrong to whoever checks it next.
2026-08-31 21:04:22 +02:00
Marc-André Bombeck e6751f0f0c Merge pull request #882 from MBombeck/fix/transposed-reference-window-v2
Drop a reference window whose floor sits above its ceiling
2026-08-31 20:35:14 +02:00
Marc-André Bombeck 963f61cf0f Drop a reference window whose floor sits above its ceiling
A lab report's reference range reaches the record by four paths. Three of
them validate that the floor does not exceed the ceiling; the document
path did not, and the catalog store writes what it is handed. An
integration run against a real Postgres confirmed the consequence: a
100/30 pair landed on the row and on the freshly minted biomarker, so
every later reading of that analyte inherited a window that cannot be
true and a high value came back reassuring.

Dropping beats swapping. A transposed pair says the transcription is
wrong, not which of the two numbers is, and inventing an order would
state something the report never printed. The verbatim string survives
either way, so nothing the document actually said is lost.

Three points, answering according to what each one is:
- the extraction schema drops the pair, because every field there is
  catch-guarded so one bad value cannot sink a 120-fact document
- the review-screen edit refuses with the wording the lab schemas
  already use, because a person can see both numbers and fix them
- the commit path drops it as the last gate, which is what covers facts
  staged before this rule existed and confirmed afterwards

parseReferenceRange has answered a transposed PRINTED window this way
since it was written, and the commit path already counts a window it
could not read at all. This extends both to the case that was readable
and cannot be true.
2026-08-31 19:38:08 +02:00
Marc-André Bombeck a852860654 Merge pull request #881 from Antiheld86/feat/measurements-write-scope
Feat/measurements write scope
2026-08-31 16:03:44 +02:00
Antiheld86 a778acac4e chore: regenerate OpenAPI spec 2026-08-31 12:48:18 +00:00
Antiheld86 7c23b14053 Teach the arrival-wiring mock about isScopedCredential
That file stubs @/lib/api-handler wholesale, so it lists the exports it
knew about when it was written. /api/measurements now reaches for
isScopedCredential to decide source attribution and whether the sync
checkpoint may move, the mock does not provide it, and every test in the
file dies on import rather than on an assertion.

`false` is the honest stub: those cases resolve as a cookie session,
which is exactly what unscoped means, so the route takes its ordinary
path through both rules.

Checked the rest of the tree rather than fixing only the file that went
red — this is the only suite mocking that module for a route which
reaches the new export. The batch route's tests mock at a different
seam and are unaffected.

Not verified here: this environment cannot generate the Prisma client,
so that file is one of the suites which fail to import for an unrelated
reason and the fix could not be run.
2026-08-31 12:14:51 +00:00
Antiheld86 19b69dee21 Fix the B8 delegation cases to actually claim a record
Three failures in the integration run, all mine, none in the product.

The two delegation cases set the account selector as a header on the
NextRequest. Nothing reads it there. `readSelectorHeader()` resolves
through `next/headers`, which this suite mocks against the shared
`headerJar`, so the carrier came back `none` and both cases quietly
exercised the ordinary own-record path instead of the one they name. The
scoped case wrote to its own record and returned 201; the wildcard
control wrote to the caller rather than the owner. Neither was testing
delegation at all.

That is worse than a broken test. The refusal these two cover is the
regression this change could most easily have shipped in silence, and
the tests standing in front of it were not looking at it.

They now set the selector on the jar, through the exported
ACCOUNT_SELECTOR_HEADER rather than a literal, so a rename cannot
reintroduce the same gap.

The third failure is unrelated and smaller: the read-leg case read the
audit row once, racing a fire-and-forget write, and reported `undefined`
for a row about to exist. It now polls, matching B1, which carries a
comment about this exact hazard that I did not follow.

Not verified here: this environment has no Docker daemon, so the
integration suite cannot be run against a real Postgres. The diagnosis
is from the mock and the resolver, not from a green run.
2026-08-31 11:57:26 +00:00
Antiheld86 56d6fb180a Make the measurement-token mint cookie-only
The mint used requireAuth() with no scope, which refuses a narrow token
but still admits a cookie-equivalent one. The reach is not the problem —
a wildcard token can already do everything this endpoint does. The
lifetimes are: a native access token lives a day, and what it mints here
lives a year. So a credential that leaked for an afternoon could leave
behind one that outlives revoking it, and the revocation would look like
it had worked.

requireCookieAuth() closes that. It is the helper the passkey
registration and trusted-device routes already use for the same reason,
and the sharing guard recognises it as cookie-only.

The prose said more than the code did, in three places: the route header
and the OpenAPI description both claimed the endpoint "cannot mint
another token", which held only for narrow tokens, and the 403 arm
described a scope refusal that a Bearer never reaches. All three now say
what is true — no Bearer credential reaches this endpoint at any scope,
and a Bearer is refused 401 before the operator switch is read.

Tests follow the status change: the integration case asserting a scoped
token cannot mint now expects 401 rather than 403, since the refusal is
authentication and not scope, and a companion case pins the wildcard —
the credential class this change is actually about — and asserts no
token row is created.
2026-08-31 11:38:16 +00:00
Timon_bed 68a3b57597 Improve lab range and trend visual alignment 2026-08-31 11:56:54 +02:00
Antiheld86 8f61e0bc6a Plainer copy on the measurement token card
The card read like API documentation sitting in a settings page: it named
the Authorization header, spelled out both endpoint paths, and listed the
scope's limits as four clauses. None of that is what someone deciding
whether to mint a token needs, and the endpoint paths were already in the
API endpoints card immediately above it.

Rewrite to the shape the MCP connector card next door uses — a short
title, one line on what the token is for, one line saying it is shown
once, and one sentence on what it can and cannot do. Drop the endpoints
note entirely rather than rephrase it, since the card above owns that.

Say the useful consequence instead of the mechanism: readings arrive as
if entered by hand, so they can be corrected. That is the thing a person
will actually notice.

Translations were revised across all seven locales — the previous German
in particular read as translated English rather than as the rest of the
app, which uses short informal sentences.
2026-08-31 09:50:47 +00:00
Antiheld86 e79709379b Fix duplicate status keys in the new OpenAPI response blocks
`stdResponses` already carries 401, 422 and 429. The three response
blocks added with the measurements:write scope each declared their own
422 (and, on the mint route, a 429) BEFORE spreading it, so the generic
wording overwrote the specific wording and TypeScript refused the
duplicate key. The build failed at auth.ts with "'422' is specified more
than once".

Move the explicit keys after the spread, which is what the MCP mint next
door already does and the only order in which a per-route description
survives.

Worth stating because the failure mode is quiet: had TypeScript allowed
it, the published contract would simply have carried "Request validation
failed" everywhere instead of naming
measurement.create.source_not_permitted and its siblings.
2026-08-31 09:22:38 +00:00
Antiheld86 cba7a0fce5 Add a self-service measurements:write API token scope
Since v1.30.17 there has been no self-service path to a token that can
write a measurement. That release made the Bearer scope default
fail-closed, which closed a real privilege-escalation hole, and removed
the generic mint at POST /api/tokens along with it. The generic mint had
been the only way to get a token that could reach /api/measurements, so
a local sensor pushed through Home Assistant or Node-RED lost its door
while the OAuth integrations kept theirs.

Add a narrow scope accepted by exactly two routes, both writes, both on
the holder's own record.

The scope constant is a leaf module beside the surface that consumes it,
matching FHIR_READ_SCOPE and the MCP scopes. requireRecordAuth grows an
options object rather than a sibling function, because the sharing
surface guard keys every leg on that one identifier and a second name
would mean two copies of the delegable declaration. AuthContext carries
the admitting scope as a single nullable string rather than the token's
permission array, so nothing downstream can re-derive an authorisation
decision from it.

A scoped credential is refused a record selector before any grant is
read. Placing the refusal above the sharing check rather than beside it
means no future widening of what a grant permits can reach one of these
tokens.

Rows are attributed MANUAL. An entry that explicitly names APPLE_HEALTH
is refused 422 rather than relabelled: that source is half the
(userId, type, source, externalId) dedup key the iOS client writes into,
it participates in the cross-source merge, and it gates the HealthKit
sync fields. For the same reason a scoped write no longer advances
User.lastSyncedAt, which the phone reads to size its undelivered window.

Also closes a narrower gap found while building this. The idempotency
wrapper resolved a replayed delegated response against a live grant
without considering which credential was presenting it, so a cached
response about a shared record could be returned to a token the handler
itself would refuse. No write was reachable that way; the response body
was.

Guards: T3 gains the mint site, T4's vocabulary gains the scope and
learns to read the requireRecordAuth form (without which this change
would open a way to widen a route that the closed vocabulary could not
see), and a new T5 freezes the set of delegable routes naming a scope.
The sharing surface guard's AST matcher reads only the first two
arguments, so it needed prose but no code.
2026-08-31 08:46:16 +00:00
Marc-André Bombeck 4308114c5b Merge pull request #879 from MBombeck/fix/lab-outlier-range-assertion
test(labs): assert the outlier's distance from the edge, not one string
2026-08-31 00:22:15 +02:00
Marc-André Bombeck 5e89a201f7 test(labs): assert the outlier's distance from the edge, not one string
Follow-up to #860, promised in review rather than asked of the
contributor. `not.toContain("left: 4%")" passes for a marker at 4.02%,
which is the same defect one rounding away, so the test now reads the
marker position and asserts it sits inside the padding at both ends.

EDGE_PADDING_PERCENT moves to module scope and is exported, so the
assertion uses the number the component clamps with instead of a copy
that can drift. It was being reallocated on every render besides.

Verified by mutation: dropping the outlier expansion puts the marker at
exactly 4 and turns this test red.
2026-08-31 00:06:50 +02:00
Marc-André Bombeck 7cca0a0710 Merge pull request #860 from TimonBed/feat/labs-ocr-openai-fix
rework of range bar ind lab list
2026-08-31 00:04:14 +02:00
Timon_bed f30a202a67 fix: keep lab outliers clear of range bar edges 2026-08-30 23:45:47 +02:00
Marc-André Bombeck b1d6765790 Merge pull request #875 from MBombeck/dependabot/npm_and_yarn/vitejs/plugin-react-6.1.0
chore(deps-dev): bump @vitejs/plugin-react from 6.0.4 to 6.1.0
2026-08-30 22:24:11 +02:00
Marc-André Bombeck 78921399fb Merge pull request #877 from MBombeck/dependabot/npm_and_yarn/radix-ui-1.6.7
chore(deps): bump radix-ui from 1.6.2 to 1.6.7
2026-08-30 22:07:32 +02:00
Marc-André Bombeck e7d40e22b0 Merge pull request #876 from MBombeck/dependabot/npm_and_yarn/lucide-react-1.34.0
chore(deps): bump lucide-react from 1.27.0 to 1.34.0
2026-08-30 22:05:58 +02:00
Marc-André Bombeck 68f33dad5f Merge pull request #874 from MBombeck/dependabot/npm_and_yarn/next/bundle-analyzer-16.3.3
chore(deps-dev): bump @next/bundle-analyzer from 16.3.1 to 16.3.3
2026-08-30 22:00:18 +02:00
Marc-André Bombeck 0be1663989 Merge pull request #873 from MBombeck/dependabot/npm_and_yarn/hookform/resolvers-5.9.1
chore(deps): bump @hookform/resolvers from 5.4.0 to 5.9.1
2026-08-30 21:58:27 +02:00
Marc-André Bombeck a4b2a1541d Merge pull request #872 from MBombeck/fix/pg-runtime-dependency
fix: declare pg as the runtime dependency it already was
2026-08-30 21:57:26 +02:00
dependabot[bot] c532f60c57 chore(deps): bump radix-ui from 1.6.2 to 1.6.7
Bumps [radix-ui](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/radix-ui) from 1.6.2 to 1.6.7.
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/radix-ui/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/1.6.7/packages/react/radix-ui)

---
updated-dependencies:
- dependency-name: radix-ui
  dependency-version: 1.6.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-30 19:17:23 +00:00
dependabot[bot] 07b32617d2 chore(deps): bump lucide-react from 1.27.0 to 1.34.0
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 1.27.0 to 1.34.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/1.34.0/packages/lucide-react)

---
updated-dependencies:
- dependency-name: lucide-react
  dependency-version: 1.34.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-30 19:02:53 +00:00
dependabot[bot] 098cc9d5d4 chore(deps-dev): bump @vitejs/plugin-react from 6.0.4 to 6.1.0
Bumps [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react) from 6.0.4 to 6.1.0.
- [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.0/packages/plugin-react)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-30 19:02:16 +00:00
dependabot[bot] 5898742fa3 chore(deps-dev): bump @next/bundle-analyzer from 16.3.1 to 16.3.3
Bumps [@next/bundle-analyzer](https://github.com/vercel/next.js/tree/HEAD/packages/next-bundle-analyzer) from 16.3.1 to 16.3.3.
- [Release notes](https://github.com/vercel/next.js/releases)
- [Commits](https://github.com/vercel/next.js/commits/v16.3.3/packages/next-bundle-analyzer)

---
updated-dependencies:
- dependency-name: "@next/bundle-analyzer"
  dependency-version: 16.3.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-30 19:01:40 +00:00
dependabot[bot] 2e6e133409 chore(deps): bump @hookform/resolvers from 5.4.0 to 5.9.1
Bumps [@hookform/resolvers](https://github.com/react-hook-form/resolvers) from 5.4.0 to 5.9.1.
- [Release notes](https://github.com/react-hook-form/resolvers/releases)
- [Commits](https://github.com/react-hook-form/resolvers/compare/v5.4.0...v5.9.1)

---
updated-dependencies:
- dependency-name: "@hookform/resolvers"
  dependency-version: 5.9.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-30 19:00:56 +00:00
Marc-André Bombeck b4c18d131a Merge pull request #871 from MBombeck/fix/codeql-action-4.37.9
ci: move every codeql-action pin to v4.37.9 in one commit
2026-08-30 20:50:25 +02:00
Marc-André Bombeck 9f07a46633 fix: declare pg as the runtime dependency it already was
The Dockerfile asserts that the standalone image can resolve pg, because
pg-boss loads it through native Node resolution. That assertion has been
passing on a coincidence: pg sat in devDependencies, and the version our own
entry pinned happened to match the one @prisma/adapter-pg pulled in, so both
names resolved to a single copy in the store and Next's file tracer packed it
whole.

Bumping the adapter to 7.10.0 moves its transitive pg to 8.23.0 while ours
stayed at 8.22.0. The tracer packs only the copy the adapter reaches, the
top-level link points at the other one, and the image fails to build on both
architectures:

    Error: Cannot find module '/app/node_modules/pg/lib/index.js'

Move pg into dependencies at ^8.23.0. The lockfile now carries one pg version
instead of two, so the two resolutions cannot drift apart again on the next
adapter release. Carries the adapter bump from #865, which cannot build alone.
2026-08-30 20:49:46 +02:00
Marc-André Bombeck eb49580271 Merge pull request #868 from MBombeck/dependabot/npm_and_yarn/zod-openapi-6.0.1
chore(deps): bump zod-openapi from 6.0.0 to 6.0.1
2026-08-30 20:47:35 +02:00
Marc-André Bombeck 95a75cd9e0 Merge pull request #862 from MBombeck/dependabot/npm_and_yarn/knip-6.32.3
chore(deps-dev): bump knip from 6.32.2 to 6.32.3
2026-08-30 20:47:27 +02:00