Added
- Single-binary packaging. HTML templates, locales, and
web/staticare embedded into the binary viago:embed; the runtime image ships only the binary (FROM scratch) and the app runs from any working directory. Static asset URLs are cache-busted with?v=<build revision>and served withCache-Control: public, max-age=3600, so a release invalidates stale JS/CSS without operator action.
Changed
HSTS_ENABLEDswitch.Strict-Transport-Securityis now governed by an explicitHSTS_ENABLEDenvironment variable (default inheritsCOOKIE_SECURE, exact prior behavior). Operators can keep secure cookies without pinning browsers to HTTPS for a year, or opt in explicitly; enabling it logs a startup note about the one-year pin.- BBT stored as nullable.
daily_logs.bbtdropsNOT NULL DEFAULT 0(migration 024, SQLite and Postgres; existing0rows are migrated toNULL).nilnow means "not measured", retiring the 0°C sentinel. - Breaking (export shape):
bbt(basal body temperature) is now omitted from JSON export entries on days without a measurement, instead of always being present as0. Consumers parsing the export must treat a missingbbtkey as "not measured". Restore stays fully backward-compatible — import reads an absent key, an explicitnull, and the legacy0all as "not measured" (docs/export.mdanddocs/openapi.yamlupdated).
Fixed
- Light-theme accent contrast raised to WCAG AA. The two colours behind the only axe colour-contrast violation (2.96:1 against the hero gradient) now clear 4.5:1; hue preserved, dark theme untouched.
Removed
- Breaking: removed the query-string form of the day-delete endpoint (
DELETE /api/v1/days?date=YYYY-MM-DD). UseDELETE /api/v1/days/{date}instead (the optionalsourceselector, if used, moves from thedate-bearing query string to a plain?source=query param on the path form).docs/openapi.yamland the browser UI have been updated accordingly. - Redundant
daily_logsdate index dropped (migration 025, both dialects). Every query path is user-scoped and already served by the(user_id, date)index; the bare-date index only added write amplification.
Security
- OIDC HTTP redirects are origin-pinned. The HTTP client used for OIDC discovery, the JWKS key fetch, and the authorization-code exchange now refuses to follow any redirect that leaves the configured issuer origin, extending the existing
jwks_uri/token_endpoint/end_session_endpointorigin pins to the HTTP requests themselves. A provider that redirects these requests cross-origin now fails closed at sign-in; same-origin redirects (path normalization) keep working. - Request bodies are bounded (16 MiB). An explicit
BodyLimitsized to the documented JSON-restore maximum; the transport-level 413 now returns the mapped, localizedrequest_too_largeenvelope instead of fasthttp's bare text.
Internal
- Lifted the transitive SQLite (
modernc.org/sqlite) andfasthttpengines to current upstream. - Split
base.htmlinto a components library underinternal/templates/components/(byte-identical defines;base.htmlkeeps only the page skeleton). - Retired the sentinel→enum error-classification layer across all domains; error mapping now switches directly on service sentinels.