From dbac3d3abd2fed824dff0f2b3bc59a0b46305884 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Sun, 26 Jul 2026 18:18:28 +0200 Subject: [PATCH] =?UTF-8?q?chore(release):=20v1.33.0=20=E2=80=94=20what=20?= =?UTF-8?q?was=20silently=20failing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 96 +++++++++++++++++++++++++++++++++++++++++++ docs/api/openapi.yaml | 2 +- package.json | 2 +- public/sw.js | 2 +- 4 files changed, 99 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f8dbca67..9ff26d31c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,102 @@ ## [Unreleased] +## [1.33.0] — 2026-07-26 + +Eight defects, and every one of them had the same shape: something failed +reliably, the code recorded it precisely, and no person ever found out. + +**"Delete All Data" deleted 13 tables out of 92 and reported success.** What +survived included mental-health questionnaires, lab results, the menstrual +record, allergies, family history, the whole document vault, every AI +conversation, and clinician share links that kept working. On the account row +itself, 11 of 119 columns were cleared, so name, insurer, insurance number, home +coordinates, profile photo and every integration credential stayed. The wipe now +covers everything the account owns except what is needed to sign in again, the +list is derived from the schema so a newly added table cannot quietly survive, +and the confirmation says what will go before you agree rather than after. + +**A device sync failed 1149 times without anyone being told.** The escalation +had no rung above "temporary", so a connection could fail hourly for weeks while +the card read "connected". Worse, providers that sync several things separately +had one healthy part erase the error recorded by a broken one, twice an hour, +including a connection that had already been parked for a dead credential. A +failing connection now shows how long it has been failing, escalates after a +day, and stops retrying after two with a reconnect button. + +**The Environment module had never once saved a row, for anyone.** One +declaration in 49 was missing the line that maps it to the database, so every +write referred to a type that does not exist. The job failed every night and +recorded that failure faithfully, and no code anywhere reads a failed job. Both +halves are fixed: the module writes, and a failing background job now names +itself on the admin page and on the affected screen. Past days can be fetched +from the weather source; the nightly job fills the last week by itself and the +backfill button covers the rest. + +**Sleep was counted twice.** A device that re-exports a night it already sent +left two overlapping in-bed periods, and both were added. One night read ten +hours in the headline and twenty in the legend. The same fault inflated the +time-asleep figure itself. Every stage total is now the measure of its own +period rather than the sum of overlapping ones. Naps are also now told apart +from the main sleep everywhere a person reads them, not just in the export. + +**Twenty-two controls could destroy something without asking.** Among them a +single tap that cleared the allergy list along with a text note, and a switch +labelled "Custom range" that deleted the stored range when switched off. Every +destructive control is now registered, and a new one cannot ship without being +classified. + +**Medication stock was written off that had not expired.** The thirty-day clock +that applies to an opened injection pen was being applied to a blister of +tablets, so pressing out the first tablet started a countdown and a month later +the rest were declared unusable. The container kind was recorded and never read. +Pens and ampoules keep the clock; blisters, bottles and inhalers do not. A +repair returns stock that was written off, and the dates that drive it can now +be seen and corrected on the item itself. + +**Insights scrolled sideways on every phone.** Two guards were watching for +exactly that and both measured the document, while the app scrolls inside an +inner area that absorbed the overflow. They now measure what actually moves. + +**A third value for gender was accepted by the app and missing from the +published contract in five places, and dropped or coerced in nine more.** A +fitness calculation scored anyone without a recorded gender using the male +coefficients, and the doctor report labelled any unrecognised value as +non-binary. Every place the field is read, written, documented or displayed was +gone through. + +### Two additions + +Medication history from a widely used iOS export tool can now be read directly, +as the file actually is, rather than converted by hand. The scheduled time and +the time taken stay two separate facts, which is what a hand-mapped file +destroys. Every column is either used, reported, or named as not read, and you +see which before you import. Seven status values are ruled on individually: only +"taken" and "skipped" become doses, and a snoozed reminder or an unanswered +notification is counted and named rather than turned into a decision you never +made. + +Behavioural patterns now cover alcohol against next-day recovery and resting +heart rate. The statistics for it were already in the app. + +### For operators + +Four migrations. `0276` adds retention indexes, `0277` adds failure-streak +tracking, `0278` scopes the intake import key per account, `0279` repairs +inventory that was wrongly expired. None deletes or rewrites a measurement. + +### Credit + +Reported by @lutzkind (sleep double-counting, the gender contract, the +Environment enum, and a run of earlier reports), @Nazza01 (the intake import, +plus the export file and the format documentation that made reading it +possible), @DrGithubble (the unit and precision work that led here) and @doenke +(the measurement table, narrowed by the reporter into something buildable). + +Two of these defects were found because someone outside this project read the +code and said what was wrong. The Environment module had been broken for every +user since it shipped and nobody inside noticed. + ## [1.32.39] — 2026-07-26 The doctor report now carries what you chose, and nothing else. diff --git a/docs/api/openapi.yaml b/docs/api/openapi.yaml index 7be123662..704a2ba43 100644 --- a/docs/api/openapi.yaml +++ b/docs/api/openapi.yaml @@ -1,7 +1,7 @@ openapi: 3.1.0 info: title: HealthLog API - version: 1.32.39 + version: 1.33.0 description: >- Self-hosted personal-health-tracking PWA — public API surface for the iOS native client and external ingest. diff --git a/package.json b/package.json index b5a3e56ec..70d975c0d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "healthlog", - "version": "1.32.39", + "version": "1.33.0", "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", diff --git a/public/sw.js b/public/sw.js index 945e43296..763fc3589 100644 --- a/public/sw.js +++ b/public/sw.js @@ -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.32.39"; + /* @sw-version-fallback */ "v1.33.0"; 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/*`