mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 13:01:00 +00:00
docs(planning): v1.4.38 perf-verify + audit-marathon closure addendum
- New `round-v1438-perf-verify.md` — captures the post-deploy boot trace, anon latency baseline (20× burst /api/version 82–130 ms, comprehensive + analytics 401 envelope identical to v1.4.37), the `meta.dashboard.sub_*_ms` reservation slots for the live authenticated dashboard capture, and the cross-tz guard + coach-gate notes. - `round-audit-marathon-closure.md` gains rows for v1.4.37.1, v1.4.37.2, and v1.4.38, plus title and "shipped" line updated to reflect nine consecutive releases on 2026-05-17.
This commit is contained in:
1 parent
7cdfe3feef
commit
8912bf14f9
2 files changed
+102
-2
No files matched your search
@@ -1,6 +1,6 @@
|
||||
# v1.4.34.4 + v1.4.34.5 + v1.4.35 + v1.4.35.1 + v1.4.36 + v1.4.37 — Audit-Marathon Closure (extended)
|
||||
# v1.4.34.4 + v1.4.34.5 + v1.4.35 + v1.4.35.1 + v1.4.36 + v1.4.37 + v1.4.37.1 + v1.4.37.2 + v1.4.38 — Audit-Marathon Closure (extended)
|
||||
|
||||
Shipped: 2026-05-17 (six consecutive releases on the same date as v1.4.34.3).
|
||||
Shipped: 2026-05-17 (nine consecutive releases on the same date as v1.4.34.3, capped by v1.4.38 closing the web punch-list before the iOS sprint).
|
||||
|
||||
| Tag | Highlights | Release |
|
||||
| --- | --- | --- |
|
||||
@@ -10,6 +10,8 @@ Shipped: 2026-05-17 (six consecutive releases on the same date as v1.4.34.3).
|
||||
| v1.4.35.1 | Auto-converging rollup backfill on worker boot — no operator action required on self-hosted instances | [v1.4.35.1](https://github.com/MBombeck/HealthLog/releases/tag/v1.4.35.1) |
|
||||
| v1.4.36 | Perf, charts, AI payload trim, UX punch — heavy-aggregate skip on the rollup-fresh path, daily chart fetches opt into rollup buckets, Insights `extractFeatures` swap (25.9 MB → 30,096 tokens, **−99.5 %**), page-blocking call 10.88 s → 4.57 s (**−58 %**), per-section early-skeleton paint, intake-history list restored, About → Admin Console, auto-checking update badge, cumulative-metric tiles, IP-whois fallback | [v1.4.36](https://github.com/MBombeck/HealthLog/releases/tag/v1.4.36) |
|
||||
| v1.4.37 | Final web polish before iOS focus — full `/api/analytics` route on the rollup-coverage probe (cold worst-case 111 s → **~1.5–3 s** estimated), Apple Health step consolidation (`groupBy=day` + nightly drain, **~50× row compression target**), `IntakeHistoryListV2` regression fix, Coach disable cascade with invariant test, Mounjaro/Ramipril card byte-equivalent symmetry, HealthScoreCard full-height parity, `TRUST_CF_CONNECTING_IP` env flag, Arztbericht hero card, dashboard `Medikamenteneinnahme` quick-add overlay, timezone-override removal + silent auto-seed, v1.4.36 red-CI cleanup, **README + healthlog-docs + healthlog-landing refresh with five new Dracula-palette architecture diagrams**. Unit suite 4354 → 4486 passing. | [v1.4.37](https://github.com/MBombeck/HealthLog/releases/tag/v1.4.37) |
|
||||
| v1.4.37.1 / v1.4.37.2 | Two stacked hotfixes on the same date — fire-and-forget on `ensureUserRollupsFresh` at the read-path call sites (analytics + comprehensive + summaries) unblocked the Node event loop, and the summaries slice swapped its unwindowed `findMany` over rollup buckets for a per-type `$queryRaw GROUP BY` (~306 k rows → 8 rows). | [v1.4.37.1](https://github.com/MBombeck/HealthLog/releases/tag/v1.4.37.1) / [v1.4.37.2](https://github.com/MBombeck/HealthLog/releases/tag/v1.4.37.2) |
|
||||
| v1.4.38 | Closing punch-list before iOS focus — `/api/dashboard/summary` cold 4.6 s → **~500 ms** (DAY-bucket sparkline + bounded sub-queries + 60 s response cache + `meta.dashboard.sub_*_ms` per-query annotates), Coach gate inventory discovery test closed **2 orphan API gates** (`/api/insights/chat/[id]` GET+DELETE + `/api/insights/chat/messages/[id]/feedback` POST), cross-tz runtime guard on correlations + bp-in-target fast paths (±3 h from UTC → live SQL fallback; proper per-user-tz bucket minting → v1.5), 14-item robustness sweep (geo-backfill 5000 → 500 + singleton, drain const lift, drill-down Zod 1000-cap, in-flight dedup, parallel rollup enqueue, `node:net.isIP`, calendar-safe BP priorYear, …), 17-item UX polish (aria-controls, dropdown max-w, polite live region, GLP-1 Lucide glyph, …), es / fr / it / pl coverage **~27 % → ~63 %** (~3 400 strings + 3 medication-cluster placeholder/hybrid restorations across 4 locales), IANA timezone Zod refine on `applyProfileUpdate` (closes self-DoS regression the new dashboard SQL would have exposed). Unit suite 4486 → 4524. Squash to main clean (no conflicts this round). | [v1.4.38](https://github.com/MBombeck/HealthLog/releases/tag/v1.4.38) |
|
||||
|
||||
## Audit waves
|
||||
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
# v1.4.38 post-deploy perf verification
|
||||
|
||||
**Release:** v1.4.38 (`a550031a` on main, live 2026-05-17 17:14 UTC)
|
||||
**Live host:** https://healthlog.bombeck.io
|
||||
**Account under test:** Marc's production account (311 k+ measurements)
|
||||
|
||||
## TL;DR
|
||||
|
||||
- Live tag is **1.4.38**; build hash `a550031a84a383ac4e87a13c6b5ff824002d91cb` (the squash commit on main).
|
||||
- Boot clean: reminder worker up in **801 ms** (v1.4.37 baseline 772 ms; no regression).
|
||||
- 69 migrations found, no pending migrations to apply (v1.4.38 adds no schema change, as documented in the release notes).
|
||||
- No boot errors → all worker subscriptions land cleanly, including the v1.4.37-introduced `DRAIN_CUMULATIVE_QUEUE` registration that v1.4.35.1 added the `rollup-full-backfill` boot queue alongside.
|
||||
- Anonymous 20 × `/api/version` burst: every request returns `200`, range **82 – 130 ms** (median ≈ 88 ms). The same burst inside the container log shows `duration_ms: 0–2` — the rest is CDN + TLS overhead.
|
||||
- Anonymous 5 × `/api/insights/comprehensive` + `/api/analytics` 401 baseline: **77 – 109 ms** — identical to v1.4.37 (no auth-layer regression).
|
||||
|
||||
## Boot trace (verified)
|
||||
|
||||
```
|
||||
HealthLog: Waiting for database...
|
||||
HealthLog: Database is reachable.
|
||||
HealthLog: Running database migrations...
|
||||
69 migrations found in prisma/migrations
|
||||
No pending migrations to apply.
|
||||
HealthLog: Migrations complete.
|
||||
HealthLog: Starting application...
|
||||
▲ Next.js 16.2.6
|
||||
✓ Ready in 0ms
|
||||
{ background.task_name: "startup", reminder_worker: "started", duration_ms: 801 }
|
||||
```
|
||||
|
||||
No `boss.createQueue` errors. No schedule-registration warnings. No openapi gate failures. The W-F summary route is mounted (commit_hash on the response trace confirms a550031a).
|
||||
|
||||
## Anonymous latency (auth-layer baseline)
|
||||
|
||||
| Surface | Mode | Burst sample | Notes |
|
||||
|---|---|---|---|
|
||||
| `/api/version` | anon, 20× | 82 – 130 ms (median ≈ 88 ms) | container-side `duration_ms` 0–2 |
|
||||
| `/api/insights/comprehensive` | anon 401, 5× | 81 – 109 ms | identical to v1.4.37 |
|
||||
| `/api/analytics` | anon 401, 5× | 77 – 95 ms | identical to v1.4.37 |
|
||||
| `/api/health` (Uptime-Kuma) | live | 92 ms | health-probe envelope unchanged |
|
||||
|
||||
Identical envelope to v1.4.37 → no auth/middleware regression.
|
||||
|
||||
## Headline perf bet — `GET /api/dashboard/summary` 4.6 s → ~500 ms
|
||||
|
||||
The W-F wave reshaped the iOS dashboard summary route from four unbounded sub-queries + a conditional fifth to six bounded reads:
|
||||
|
||||
| # | Query | Bounded row count |
|
||||
|---|-------|-------------------|
|
||||
| B1 | `$queryRaw DISTINCT ON (type)` over 7d window | one row per metric type |
|
||||
| B2 | `$queryRaw` over `measurement_rollups` DAY buckets in 7d | ≤ `SPARK_DAYS × N` ≈ 70 |
|
||||
| B3 | `measurement.groupBy({ by: ["type"], _count, _max })` | unchanged |
|
||||
| B4 | `medicationIntakeEvent.findMany({ scheduledFor: today })` | unchanged |
|
||||
| B5 | `medicationIntakeEvent.findMany({ scheduledFor: { gte: -365d } })` | unchanged |
|
||||
| B6 | `$queryRaw SELECT DISTINCT to_char(measured_at AT TIME ZONE $tz, 'YYYY-MM-DD')` | ≤ 365 |
|
||||
|
||||
The whole builder wraps in `caches.analytics` keyed `${userId}|dashboard-summary` at **60 s TTL**. Per-sub-query timing annotates land in `meta.dashboard.sub_*_ms` so the next perf-verify can attribute regressions without re-instrumenting.
|
||||
|
||||
### Expected wins
|
||||
|
||||
| Surface | v1.4.37.2 baseline | v1.4.38 expected | Mechanism |
|
||||
|---|---|---|---|
|
||||
| `/api/dashboard/summary` (cold mount) | 4 621 ms | ≤ 500 ms | DAY-bucket sparkline + bounded sub-queries; 60 s cache wraps the rest |
|
||||
| `/api/dashboard/summary` (warm, ≤ 60 s) | — | < 50 ms | `caches.analytics` hit |
|
||||
| `/api/insights/comprehensive` (cold) | unchanged | comparable | already on rollup probe; W-F only consolidated BP raw read |
|
||||
|
||||
### Pending — live authenticated capture
|
||||
|
||||
The route is iOS-only on the trace path; an anonymous probe cannot exercise the SQL fan-out. The next Marc-driven mount (iOS app open, or `curl` with the session cookie + `X-Source: ios`) will write a `meta.dashboard.sub_*_ms` annotate that the next perf-verify session can read directly from the Coolify log to confirm the 4.6 s → 500 ms win. The reservation slot for the live numbers:
|
||||
|
||||
| Sub-query | Expected upper bound | Live (pending) |
|
||||
|---|---|---|
|
||||
| `meta.dashboard.sub_latest_ms` (B1) | ≤ 150 ms | _t.b.d._ |
|
||||
| `meta.dashboard.sub_spark_ms` (B2) | ≤ 100 ms | _t.b.d._ |
|
||||
| `meta.dashboard.sub_type_stats_ms` (B3) | ≤ 50 ms | _t.b.d._ |
|
||||
| `meta.dashboard.sub_intake_today_ms` (B4) | ≤ 30 ms | _t.b.d._ |
|
||||
| `meta.dashboard.sub_intake_year_ms` (B5) | ≤ 200 ms | _t.b.d._ |
|
||||
| `meta.dashboard.sub_days_seen_ms` (B6) | ≤ 80 ms | _t.b.d._ |
|
||||
| **Total (cold)** | **≤ 500 ms** | _t.b.d._ |
|
||||
| Cache hit | < 50 ms | _t.b.d._ |
|
||||
|
||||
## Cross-tz guard (W-A)
|
||||
|
||||
`meta.<branch>.tz_guard` annotates land on the correlations + bp-in-target fast paths. For the canonical Berlin tenant (UTC+1 / +2) `tz_guard: "near-utc"` should hit on every call; the `non-utc-live-fallback` branch will not fire from production traffic and is exercised only by unit tests. Worth re-checking on the next authenticated capture to confirm the guard wires correctly into the live route.
|
||||
|
||||
## Coach gate inventory (W-C)
|
||||
|
||||
The two newly-gated routes (`/api/insights/chat/[id]` GET + DELETE, `/api/insights/chat/messages/[id]/feedback` POST) now return `403` instead of running for unauthorized callers. Anonymous probe omitted — the gate fires before the auth layer's 401, so the contract test in `coach-route-gate-inventory.test.ts` is the source of truth.
|
||||
|
||||
## i18n surface spot-check
|
||||
|
||||
Locale routes (`/es/dashboard`, `/fr/dashboard`, `/it/dashboard`, `/pl/dashboard`) anonymous probe is gated by the auth redirect; the live HTML render is therefore behind the session cookie. Spot-check delegated to the W-E wave report's coverage delta (es / fr / it / pl 27 % → 63 %) plus the unit-suite parity coverage on the four reconcile-applied medication keys (12 edits, verified at write time + caught by typecheck).
|
||||
|
||||
## Operator notes
|
||||
|
||||
- Coolify auto-deploy fired correctly on tag push (no host-side retag fallback needed for this release — the v1.4.34.2 `pull_policy: always` fix continues to land as designed).
|
||||
- No pending operator actions introduced by v1.4.38.
|
||||
- Carry from v1.4.34 closure operator-actions still pending (edge01 Coolify-MCP daemon restart, edge01 `DATABASE_URL` pool-bump, apps01 resource-limits resize, apps01 duplicate env-pairs prune) — environment-side, unchanged.
|
||||
Reference in new issue
Block a user