mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-13 22:32:04 +00:00
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.
This commit is contained in:
1 parent
cba389515c
commit
c462d9a282
4 files changed
+81
-18
No files matched your search
+78
-15
@@ -1,13 +1,14 @@
|
||||
# Changelog
|
||||
|
||||
## [Unreleased]
|
||||
## [1.38.1] — 2026-09-01
|
||||
|
||||
You can push readings in from your own hardware again.
|
||||
You can push readings in from your own hardware again, and a lab reading
|
||||
shows where it sits against its reference range at a glance.
|
||||
|
||||
Since v1.30.17 there was no way to do it. That release made API tokens
|
||||
enforce their scope, which closed a real hole — a token issued for
|
||||
Since v1.30.17 there was no way to push a reading in. That release made API
|
||||
tokens enforce their scope, which closed a real hole (a token issued for
|
||||
medication intake had been reaching every other endpoint, the full backup
|
||||
export included — and removed the generic "create API token" button along
|
||||
export included) and removed the generic "create API token" button along
|
||||
with it. What went unnoticed was that the button had been the only
|
||||
self-service route to a token that could write a measurement. A scale or a
|
||||
watch bridge piped through Home Assistant had no door left, and the OAuth
|
||||
@@ -17,19 +18,31 @@ There is now a token for exactly that job, and for nothing else.
|
||||
|
||||
### Added
|
||||
|
||||
- **A measurement ingest token, minted from Settings → API & Tokens.** It
|
||||
posts readings to `/api/measurements` and `/api/measurements/batch`, on
|
||||
your own record. That is the whole list. It cannot read a reading back,
|
||||
cannot change or delete one, cannot reach the export, and cannot mint
|
||||
another token — so a credential sitting in a container you did not write
|
||||
has a worst case of junk in your own record, not your health history
|
||||
leaving the building. Shown once, expires after a year, and revoked from
|
||||
the same page as every other token.
|
||||
- **A measurement ingest token, minted from Settings → API & Tokens.**
|
||||
Contributed by @Antiheld86 in #881, from their proposal in #878. It posts
|
||||
readings to `/api/measurements` and `/api/measurements/batch`, on your own
|
||||
record. That is the whole list. It cannot read a reading back, cannot
|
||||
change or delete one, cannot reach the export, and cannot mint another
|
||||
token, so a credential sitting in a container you did not write has a
|
||||
worst case of junk in your own record, not your health history leaving
|
||||
the building. Shown once, expires after a year, and revoked from the same
|
||||
page as every other token.
|
||||
- **A guide for wiring one up**, with a worked Home Assistant
|
||||
`rest_command` and automation, the measurement types a scale or a watch
|
||||
bridge tends to report, and what each error response means.
|
||||
- The API endpoint list on that settings page now shows the two ingest
|
||||
endpoints alongside the medication one.
|
||||
- **A reference-range bar beside every lab reading**, contributed by
|
||||
@TimonBed in #860 and #880. The lab list, its mobile cards and the history
|
||||
table on an analyte's page carry a compact bar: the reference window in
|
||||
green, the reading as a marker on it, blue below the window, amber above
|
||||
it. A range with only a minimum or only a maximum gets a bar too, with
|
||||
the one stated bound labelled. A reading far outside its window (vitamin
|
||||
D at 7 against a floor of 30, say) widens the bar's scale so the marker
|
||||
stays visible instead of sitting pinned to the edge. In the list the status badge, the bar and the trend
|
||||
sparkline line up in columns across rows, and every point on the
|
||||
sparkline takes the colour the bar gives it. A qualitative reading, or one
|
||||
without a range, shows no bar.
|
||||
|
||||
### Changed
|
||||
|
||||
@@ -43,15 +56,65 @@ There is now a token for exactly that job, and for nothing else.
|
||||
have: the checkpoint records that your phone delivered what it was
|
||||
holding, and a scale advancing it could make the phone skip a window of
|
||||
its own samples.
|
||||
- The below-range and above-range badges on a lab reading carry a light
|
||||
tint (blue below, amber above) instead of the neutral grey they shared;
|
||||
in range stays neutral. Part of #860.
|
||||
- Routine dependency updates: the Prisma Postgres adapter to 7.10.0 (see
|
||||
Fixed), and the Argon2 binding, the WebAuthn server library, Radix,
|
||||
Lucide, the form resolvers and the dev tooling by a patch or minor each.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Lab OCR with a GPT-5 model on the OpenAI provider path (your own key or
|
||||
the operator's admin key), fixed by @TimonBed in #861. The list of models
|
||||
the app trusts to read an image stopped at `gpt-4o`, `gpt-4.1`,
|
||||
`gpt-4-turbo` and the full o-series, so a GPT-5 model was judged unable
|
||||
to read a photo and never sent one; the Codex path already knew better.
|
||||
The extraction call's completion budget doubles from 4000 to 8000 tokens,
|
||||
because a GPT-5 model spends part of it on reasoning and a dense report's
|
||||
JSON was being cut off before the last row. And when the provider itself
|
||||
fails, the error now says so ("The configured AI provider could not
|
||||
process this report") and the server log carries the upstream status,
|
||||
model and error excerpt, where it used to blame the photo and ask for a
|
||||
clearer one.
|
||||
- A lab report imported as a document could leave a reference window whose
|
||||
floor sits above its ceiling on the record. The bounds come from the
|
||||
extraction: when a report prints no range text, the two numbers the model
|
||||
reported are the whole of the window, and a transposed pair (100 as the
|
||||
low bound, 30 as the high) went through unchecked. Manual entry, the OCR
|
||||
path and the biomarker endpoint all refuse such a pair; the document path
|
||||
did not, and when the analyte was new to the record the pair was also
|
||||
written to its freshly minted catalog marker, so every later reading of
|
||||
that analyte was judged against a window that cannot be true. The pair is
|
||||
now dropped rather than swapped, because a transposed range says the
|
||||
transcription is wrong and not which of the two numbers is; the verbatim
|
||||
range text survives, so nothing the report actually printed is lost. The
|
||||
extraction drops it, editing a staged fact on the review screen refuses
|
||||
it with the same message the lab forms use, and confirming a fact drops
|
||||
it as the last gate, which is what covers facts staged before this rule
|
||||
existed. Counted as `labs.referenceRange.transposed` in the wide events.
|
||||
The trend sparkline had read the same pair as a minimum-only range and
|
||||
painted a high value green; it now shows a neutral point, as the range
|
||||
bar next to it already showed nothing (#882).
|
||||
- Bumping the Prisma Postgres adapter to 7.10.0 broke the image build on
|
||||
both architectures, before any release carried it, with
|
||||
`Cannot find module '/app/node_modules/pg/lib/index.js'`. `pg` had sat in
|
||||
devDependencies, and the assertion that the standalone image can resolve
|
||||
it (pg-boss loads it by plain Node resolution) had passed only because our
|
||||
pin and the adapter's happened to agree on a version; the bump moved the
|
||||
adapter's copy to 8.23.0 while ours stayed at 8.22.0, the file tracer
|
||||
packed only the adapter's copy, and the top-level link pointed at the
|
||||
other. `pg` is a runtime dependency now and the lockfile carries one copy,
|
||||
so the two cannot drift apart on the next adapter release (#872).
|
||||
|
||||
### Security
|
||||
|
||||
- The token is confined to your own record. Pointing it at a record
|
||||
somebody has shared with you is refused, and refused before the sharing
|
||||
grant is even consulted — so no future change to what sharing permits can
|
||||
grant is even consulted, so no future change to what sharing permits can
|
||||
widen what one of these tokens reaches.
|
||||
- Minting one requires being signed in on the web. No API token can mint
|
||||
another, whatever it is allowed to do — the sign-in a phone holds lasts a
|
||||
another, whatever it is allowed to do: the sign-in a phone holds lasts a
|
||||
day and what it could mint here lasts a year, so allowing it would let a
|
||||
credential that leaked for an afternoon leave behind one that outlives
|
||||
cancelling it.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: HealthLog API
|
||||
version: 1.38.0
|
||||
version: 1.38.1
|
||||
description: >-
|
||||
Self-hosted personal-health-tracking PWA — public API surface for the iOS native client and external ingest.
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "healthlog",
|
||||
"version": "1.38.0",
|
||||
"version": "1.38.1",
|
||||
"description": "Self-hosted personal-health-tracking PWA with Withings integration, AI insights, and doctor-report PDF export.",
|
||||
"license": "PolyForm-Noncommercial-1.0.0",
|
||||
"homepage": "https://healthlog.dev",
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ try {
|
||||
// v1.4.38.4 → v1.4.42. Do not hand-edit; bump `package.json` and rebuild.
|
||||
const CACHE_VERSION =
|
||||
(typeof self !== "undefined" && self.__APP_VERSION__) ||
|
||||
/* @sw-version-fallback */ "v1.38.0";
|
||||
/* @sw-version-fallback */ "v1.38.1";
|
||||
const STATIC_CACHE = `healthlog-static-${CACHE_VERSION}`;
|
||||
const PAGE_CACHE = `healthlog-pages-${CACHE_VERSION}`;
|
||||
// v1.18.6 — read-only data cache for a curated allowlist of safe GET `/api/*`
|
||||
|
||||
Reference in new issue
Block a user