mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 04:50:59 +00:00
Consolidated hotfix landing the findings from a six-axis audit
covering mobile security, UX + accessibility, code quality + docs,
README + discoverability, web performance, and mobile-deep responsive
behaviour. None of the changes break the public API or the existing
data shape; every fix is additive and SAFE under the v1.4.34.x web
freeze. Full audit reports live in `.planning/round-audit-*.md`.
Security
- Password rotation now wipes API tokens + refresh tokens in the
same `$transaction` as session revocation. A stolen iOS Bearer no
longer survives a user-initiated password change or an admin reset.
- `/.well-known/` proxy bypass tightened to an explicit-allowlist
`Set`. Stale `/api/auth/codex/callback` PUBLIC_PATHS entry dropped.
- HSTS gains `preload`. Withings host removed from the global CSP
and gated to the integration's own routes.
- `getClientIp` warns once per process on `TRUST_PROXY_HOPS`/XFF
mismatch + exposes a tagged helper for tighter universal buckets.
- Service worker rejects off-origin notification-click URLs. Offline
fallback body switched to a locale-neutral icon. Manifest gains
`scope`, `id`, `display_override`.
UX + accessibility
- i18n leaks closed on Dialog/Sheet close-X, ChartSkeleton's loading
announcement, and the notifications-section breadcrumb.
- Focus rings on bottom-nav, the More overflow button, and the
mobile top-bar user menu.
- Tap-target floor: Input / NativeSelect / Select / DateTimeInput
switch to `h-11 sm:h-10`.
- Admin chip-strip auto-scroll-into-view (matches v1.4.33 settings).
- List-page subtitles visible on mobile.
- Insights empty-state CTA vocabulary normalised so the link opens
the right measurement form (was silently failing for
BODY_TEMPERATURE / BLOOD_GLUCOSE / PULSE).
Mobile-deep
- `viewport.themeColor` reacts to light/dark mode.
- TopBar + Coach FAB reserve safe-area-inset-top / -bottom for
notched iPhones.
- Sonner toaster switches to `theme="system"`.
Code quality
- `SESSION_SECRET` dropped — the env var was documented as required
but never read by code. Three secrets, not four. Self-hosters
upgrading can delete the existing line.
- `toJson<T>()` helper consolidates seven Prisma JSON-cast sites.
- `db-compat.ts` gains a header docstring naming it the
schema-bootstrap path.
- Passkey response types adopted from `@simplewebauthn/server`;
`any` + eslint-disable pragmas drop out.
- Zero-TODO CI gate added at `.github/workflows/no-todo-markers.yml`.
Documentation + discoverability
- README rework: How-it-compares matrix, Apple Health + AI Coach
promoted to standalone Key-Features bullets, status block, latest
release + GHCR badges, OpenAPI pointer, three-secret Quick Start.
- openGraph + twitter cards now carry `images` and a
`summary_large_image` Twitter card.
- GitHub repo metadata: description tightened from 290 to 156
chars + keyword-front, `homepageUrl` flipped from a personal
tenant to the demo site, six generic / PII-adjacent topics
swapped for six high-intent ones.
- Five new user-facing docs: `docs/self-hosting/getting-started.md`,
`docs/self-hosting/reverse-proxy.md`,
`docs/integrations/apple-health.md`,
`docs/integrations/withings.md`,
`docs/integrations/ai-providers.md`.
- `docs/README.md` clarifies the docs tree as internal playbooks
vs the user-facing `docs.healthlog.dev` site.
53 lines
2.4 KiB
Markdown
53 lines
2.4 KiB
Markdown
# Scaling: web/worker container split (v1.4 G3)
|
|
|
|
The default `docker compose up` launches a single container that runs
|
|
both the Next.js HTTP server AND the pg-boss worker. That works fine
|
|
for a personal deployment but is hard to scale horizontally because
|
|
every replica also runs the full reminder/insight cron schedule.
|
|
|
|
v1.4 introduces an environment-variable gate so the same image can be
|
|
deployed in three modes:
|
|
|
|
| `HEALTHLOG_PROCESS_TYPE` | Web | Worker | Use when |
|
|
| ------------------------ | --- | ------ | ------------------------- |
|
|
| `all` (default) | ✅ | ✅ | single-host self-hosting |
|
|
| `web` | ✅ | ❌ | scaling HTTP horizontally |
|
|
| `worker` | ❌ | ✅ | dedicated job worker |
|
|
|
|
## How to split
|
|
|
|
1. Edit `docker-compose.yml`: set `HEALTHLOG_PROCESS_TYPE=web` on the
|
|
`app` service and uncomment the `app-worker` service block at the
|
|
bottom (it ships with `HEALTHLOG_PROCESS_TYPE=worker` baked in).
|
|
2. Make sure both containers see the same `DATABASE_URL`,
|
|
`ENCRYPTION_KEY` (or `ENCRYPTION_KEYS`), and `API_TOKEN_HMAC_KEY`.
|
|
3. `docker compose up -d --build`.
|
|
|
|
Both containers connect to the same Postgres. pg-boss claims jobs
|
|
atomically via row-level locking, so it is safe to run multiple worker
|
|
replicas — they will share the load.
|
|
|
|
## Healthchecks
|
|
|
|
- `app` (web) healthcheck: `wget /api/version` every 30s.
|
|
- `app-worker` does not expose a port; its liveness is reported into
|
|
the `worker_status` table on every reminder pass and surfaced through
|
|
`/api/admin/worker-status`.
|
|
|
|
The web container does NOT depend on the worker, and vice versa, so
|
|
neither container's startup can deadlock the other. The shared
|
|
dependency is Postgres; both wait on `db: condition: service_healthy`.
|
|
|
|
## Caveats
|
|
|
|
- Background tasks that touch user-scoped Wide Events (e.g. reminder
|
|
notifications) emit telemetry from the worker; configure `LOKI_*`
|
|
env vars on the worker if you want them.
|
|
- The off-host backup job runs in the worker only. The admin
|
|
`POST /api/admin/backup/test` endpoint runs in the web container and
|
|
exercises the same S3 credentials — set `BACKUP_*` env vars on BOTH.
|
|
- The startup gate (`assertSubsystemEnabled`) refuses to boot the
|
|
reminder worker when `HEALTHLOG_PROCESS_TYPE=web`, so an accidental
|
|
cross-mode invocation aborts immediately instead of silently doubling
|
|
cron load.
|