mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-07 04:12:04 +00:00
chore(release): fold in the coach discriminant, the dependency bumps, and the notes the audit found wrong
This commit is contained in:
1 parent
5a71f376d4
commit
4be01a67f0
22 files changed
+252
-489
No files matched your search
@@ -35,7 +35,7 @@ jobs:
|
||||
COACH_EVAL_API_KEY: ${{ secrets.COACH_EVAL_API_KEY }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ jobs:
|
||||
if: github.actor == 'dependabot[bot]'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ jobs:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Checkout full history
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -129,7 +129,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
|
||||
@@ -150,7 +150,7 @@ jobs:
|
||||
# Image is built but not pushed in that case.
|
||||
- name: Log in to GitHub Container Registry
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
|
||||
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
@@ -350,7 +350,7 @@ jobs:
|
||||
echo "IMAGE_REF=${REGISTRY}/${IMAGE_NAME,,}" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
|
||||
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
|
||||
@@ -45,7 +45,7 @@ jobs:
|
||||
NODE_ENV: production
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ jobs:
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
|
||||
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
timeout-minutes: 10
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Scan src/ for TODO/FIXME/XXX/HACK markers
|
||||
run: |
|
||||
|
||||
@@ -71,7 +71,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Log in to GHCR
|
||||
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
|
||||
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
|
||||
|
||||
@@ -66,7 +66,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
|
||||
|
||||
@@ -91,7 +91,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -106,7 +106,7 @@ jobs:
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Build Docker image
|
||||
run: docker build -t healthlog:scan .
|
||||
|
||||
+19
-8
@@ -25,6 +25,11 @@ 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.
|
||||
|
||||
One limit worth naming rather than leaving to be discovered: the ledger
|
||||
remembers a single failing part per provider. If two parts fail at overlapping
|
||||
times, the recovery of the later one still clears the error of the earlier. That
|
||||
is narrower than the case this fixes, and it is not closed.
|
||||
|
||||
**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
|
||||
@@ -38,8 +43,7 @@ backfill button covers the rest.
|
||||
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.
|
||||
period rather than the sum of overlapping ones.
|
||||
|
||||
**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
|
||||
@@ -77,8 +81,12 @@ see which before you import. Seven status values are ruled on individually: only
|
||||
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.
|
||||
The Coach can tell "you never recorded this" apart from "you recorded it, but
|
||||
outside the range I looked at". Someone with 1,597 imported glucose readings
|
||||
from April 2024 was told there was no glucose data at all, and the Coach then
|
||||
changed the subject, because one reason code covered both situations and the
|
||||
instruction to move on fired on both. It now says what is actually true and
|
||||
offers to look further back.
|
||||
|
||||
### For operators
|
||||
|
||||
@@ -89,10 +97,13 @@ 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).
|
||||
Environment enum, the Coach retrieval window, and a run of earlier reports),
|
||||
@Nazza01 (the intake import, plus the export file and the format documentation
|
||||
that made reading it possible) and @DrGithubble (the unit and precision work
|
||||
that led here).
|
||||
|
||||
@doenke's measurement table is not in this release. An earlier draft of these
|
||||
notes said it was and credited him for it, which was wrong on both counts.
|
||||
|
||||
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
|
||||
|
||||
+5
-5
@@ -77,13 +77,13 @@
|
||||
"jose": "^6.2.3",
|
||||
"jspdf": "^4.2.1",
|
||||
"jspdf-autotable": "^5.0.8",
|
||||
"lucide-react": "^1.18.0",
|
||||
"lucide-react": "^1.27.0",
|
||||
"mmdb-lib": "^3.0.2",
|
||||
"next": "16.2.11",
|
||||
"next-themes": "^0.4.6",
|
||||
"nodemailer": "9.0.3",
|
||||
"otpauth": "^9.5.1",
|
||||
"p-limit": "^7.3.0",
|
||||
"p-limit": "^7.3.1",
|
||||
"pg-boss": "^12.26.0",
|
||||
"prisma": "^7.8.0",
|
||||
"qrcode": "^1.5.4",
|
||||
@@ -92,7 +92,7 @@
|
||||
"react-day-picker": "^10.0.1",
|
||||
"react-dom": "19.2.7",
|
||||
"react-hook-form": "7.81.0",
|
||||
"recharts": "^3.8.1",
|
||||
"recharts": "^3.10.1",
|
||||
"rrule": "^2.8.1",
|
||||
"sax": "^1.6.0",
|
||||
"sonner": "^2.0.7",
|
||||
@@ -107,7 +107,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@axe-core/playwright": "^4.12.1",
|
||||
"@next/bundle-analyzer": "^16.2.9",
|
||||
"@next/bundle-analyzer": "^16.2.12",
|
||||
"@playwright/test": "^1.60.0",
|
||||
"@tailwindcss/postcss": "^4",
|
||||
"@testcontainers/postgresql": "^12.0.3",
|
||||
@@ -118,7 +118,7 @@
|
||||
"@types/react": "^19",
|
||||
"@types/react-dom": "^19",
|
||||
"@types/web-push": "^3.6.4",
|
||||
"@vitejs/plugin-react": "^5.1.4",
|
||||
"@vitejs/plugin-react": "^6.0.4",
|
||||
"@vitest/coverage-v8": "^4.1.5",
|
||||
"eslint": "^9",
|
||||
"eslint-config-next": "16.2.6",
|
||||
|
||||
Generated
+195
-447
File diff suppressed because it is too large.
Load diff
@@ -21,3 +21,7 @@ allowBuilds:
|
||||
ssh2: false
|
||||
tesseract.js: false
|
||||
unrs-resolver: false
|
||||
|
||||
minimumReleaseAgeExclude:
|
||||
- "@next/bundle-analyzer@16.2.12"
|
||||
- lucide-react@1.27.0
|
||||
@@ -1774,7 +1774,7 @@ model Measurement {
|
||||
// user_id` an index-only scan that converges to empty. Same partial-predicate
|
||||
// reason it is omitted here.
|
||||
// `measurements_tombstone_purge_idx` is a partial index over `(deleted_at)
|
||||
// WHERE deleted_at IS NOT NULL` — see migration 0277 (v1.32.40). Every
|
||||
// WHERE deleted_at IS NOT NULL` — see migration 0276 (v1.33.0). Every
|
||||
// other deleted_at index here is partial on IS NULL, which is the live-rows
|
||||
// predicate and the opposite of what the nightly tombstone purge asks for;
|
||||
// without this one the purge planned a sequential scan and could not finish
|
||||
@@ -2871,7 +2871,7 @@ model MedicationIntakeEvent {
|
||||
@@index([userId, scheduledFor])
|
||||
@@index([userId, medicationId, takenAt])
|
||||
// `medication_intake_events_tombstone_purge_idx` is a partial index over `(deleted_at)
|
||||
// WHERE deleted_at IS NOT NULL` — see migration 0277 (v1.32.40). Every
|
||||
// WHERE deleted_at IS NOT NULL` — see migration 0276 (v1.33.0). Every
|
||||
// other deleted_at index here is partial on IS NULL, which is the live-rows
|
||||
// predicate and the opposite of what the nightly tombstone purge asks for;
|
||||
// without this one the purge planned a sequential scan and could not finish
|
||||
@@ -3888,7 +3888,7 @@ model MoodEntry {
|
||||
// (v1.28.46 H4), serving the note-encryption boot-discovery scan. Raw SQL
|
||||
// only (partial predicate not expressible in Prisma).
|
||||
// `mood_entries_tombstone_purge_idx` is a partial index over `(deleted_at)
|
||||
// WHERE deleted_at IS NOT NULL` — see migration 0277 (v1.32.40). Every
|
||||
// WHERE deleted_at IS NOT NULL` — see migration 0276 (v1.33.0). Every
|
||||
// other deleted_at index here is partial on IS NULL, which is the live-rows
|
||||
// predicate and the opposite of what the nightly tombstone purge asks for;
|
||||
// without this one the purge planned a sequential scan and could not finish
|
||||
@@ -4329,10 +4329,10 @@ model AuditLog {
|
||||
// this three-column index serves both the findFirst and the take:5 as
|
||||
// an index range scan over the highest-churn table. See migration 0123.
|
||||
@@index([userId, action, createdAt(sort: Desc)])
|
||||
// v1.32.40 — the retention purge filters on `createdAt` alone. Every index
|
||||
// v1.33.0 — the retention purge filters on `createdAt` alone. Every index
|
||||
// above leads with `userId` or `action`, so the purge planned a sequential
|
||||
// scan and could not finish inside statement_timeout on an instance with
|
||||
// enough history. See migration 0277.
|
||||
// enough history. See migration 0276.
|
||||
@@index([createdAt])
|
||||
@@map("audit_logs")
|
||||
}
|
||||
@@ -4487,7 +4487,7 @@ model ImportJob {
|
||||
model MedicationIntakeImportJob {
|
||||
id String @id @default(cuid())
|
||||
userId String @map("user_id")
|
||||
/// v1.32.40 (migration 0276) — nullable. The per-medication import route
|
||||
/// v1.33.0 (migration 0278) — nullable. The per-medication import route
|
||||
/// scopes its job to one medication and names it here. A dose history
|
||||
/// exported from another tracker covers a whole regimen in one file — the
|
||||
/// reported export named sixteen medications across 3,395 rows — so that job
|
||||
|
||||
@@ -363,7 +363,7 @@ const REGISTRY: DestructiveEntry[] = [
|
||||
{
|
||||
file: "components/records/allergy-manager.tsx",
|
||||
destroys: "one allergy record",
|
||||
recovery: "tombstoned-no-restore",
|
||||
recovery: "permanent",
|
||||
confirm: ["DeleteButton"],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -16,7 +16,7 @@ vi.mock("@/lib/ai/coach/snapshot", () => ({
|
||||
buildCoachSnapshot(userId, scope),
|
||||
}));
|
||||
|
||||
// v1.32.40 (#648) — an empty window read is no longer reported as absence until
|
||||
// v1.33.0 (#648) — an empty window read is no longer reported as absence until
|
||||
// the availability probe has confirmed the record is empty. Stub the probe's
|
||||
// reads to "nothing stored", which is what these dispatch assertions mean by an
|
||||
// absent section; `coach-availability-window-honesty.test.ts` owns the other
|
||||
|
||||
@@ -31,7 +31,7 @@ export function getAuditLogRetentionDays(): number {
|
||||
/**
|
||||
* Delete audit rows past the retention horizon, in bounded batches.
|
||||
*
|
||||
* Until v1.32.40 this was one unbounded `deleteMany` on `created_at < cutoff`.
|
||||
* Until v1.33.0 this was one unbounded `deleteMany` on `created_at < cutoff`.
|
||||
* Every index on the table leads with `user_id` or `action`, so the predicate
|
||||
* had none and the statement planned a sequential scan plus index maintenance
|
||||
* on every removed row. Past the 60-second `statement_timeout` that aborts and
|
||||
|
||||
@@ -32,7 +32,7 @@ function tombstoneCutoff(now: Date): Date {
|
||||
* Hard-delete soft-deleted measurement rows whose `deletedAt` is older than
|
||||
* the retention horizon.
|
||||
*
|
||||
* Batched. Until v1.32.40 this was one unbounded `deleteMany` over a predicate
|
||||
* Batched. Until v1.33.0 this was one unbounded `deleteMany` over a predicate
|
||||
* that no index supported, which meant a backlog large enough to exceed the
|
||||
* 60-second `statement_timeout` could never be drained: the statement aborted,
|
||||
* the transaction rolled back, and the next night ran the identical statement
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* it, and the job that was supposed to make deletion real never completes.
|
||||
*
|
||||
* The fix has three parts and this file is one of them:
|
||||
* - the predicates get indexes that match them (migration 0277);
|
||||
* - the predicates get indexes that match them (migration 0276);
|
||||
* - the delete runs in bounded batches, so no single statement is on the
|
||||
* hook for the whole backlog;
|
||||
* - a run that stops at the cap says so, so "still draining" and "nothing
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* v1.32.40 — the retention purges have to be able to fail out loud.
|
||||
* v1.33.0 — the retention purges have to be able to fail out loud.
|
||||
*
|
||||
* Both handlers used to catch every error into a wide-event warning and return
|
||||
* normally. pg-boss then recorded a successful job, so a purge that aborted on
|
||||
|
||||
@@ -185,7 +185,7 @@ export async function handleMeasurementTombstoneCleanup(
|
||||
// v1.7.0 sync — prune tombstones across all three sync domains on
|
||||
// the same retention horizon.
|
||||
//
|
||||
// v1.32.40 — sequential rather than parallel. Each leg now walks its
|
||||
// v1.33.0 — sequential rather than parallel. Each leg now walks its
|
||||
// backlog in batches, and three concurrent walks against the three
|
||||
// densest tables competed for the worker pool for no gain: the job has
|
||||
// the whole night.
|
||||
|
||||
Reference in new issue
Block a user