v1.5.5 gave every retired medication feature a home on the detail page, but the page still carried the create/edit affordances that belong on the list. This release turns /medications/[id] into a pure history surface, collapses every setting into one advanced sheet, consolidates the pre-v1.5.0 granular step rows that bloated the per-sample read path, and finishes the outbound-fetch migration the safeFetch wrapper started.
Added
- Legacy step consolidation — a pg-boss job folds pre-v1.5.0 granular
ACTIVITY_STEPSrows into one canonical daily-total row per user per day (timezone-anchored) and soft-deletes the originals. A day already carrying a post-v1.5.0stats:total is left untouched (no double-count). Discovery enqueues only users still holding live legacy rows, so the pass converges and is idempotent across reboots. Migration0087adds a partial index for the discovery scan. healthlog/safe-fetch-requiredESLint rule — bans rawfetch(outside the wrapper, exempting only genuine same-origin relative paths.
Changed
/medications/[id]is now a pure history view — the Today's-dose card stays on the list page; the detail page reads past intake, cadence summary, and trends only. Every setting moves into a new advanced-settings sheet reached from the header, and the edit trigger becomes a two-option picker. The list page is unchanged.- Outbound-fetch migration finished — Withings, Codex OAuth + SSE, the bug-report comment, and the operator-host calls (Umami, GlitchTip, Loki) all route through
safeFetch; operator-supplied hosts pin the connect-time public-IP guard. /api/insights/layoutis registered in the OpenAPI spec.
Fixed
- Intake-edit dialog now seeds from the row's real values instead of an empty stub.
- Step consolidation skips a unique-constraint-colliding day instead of stranding it on every boot.
- Avatar upload reads the body once under a bounded cap, no longer over-buffering on the abort path.
- The egress lint exemption rejects protocol-relative and backslash absolute URLs.
Removed
- The dead wizard landing-intent path left over after the pure-history rewrite.