mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 12:32:43 +00:00
docs: sync README, AGENTS, CLAUDE, OpenAPI, migration guide for v1.4 (#147)
The v1.4 marathon and the v1.4.1 cycle that followed (per-section
admin extraction, Postgres testcontainers integration suite,
Playwright + axe-core E2E foundation) landed several user- and
operator-facing changes that hadn't been backfilled into the docs
shipped inside the repo. This commit closes that drift.
README.md
- Adds Multi-tenant ready and Test connection buttons feature
bullets.
- Tech-stack model count 25 → 26 (RefreshToken added in v1.4.0).
- API reference: new "Public + v1.4 additions" section listing
/api/version, the five Test connection endpoints, the two refresh
endpoints, and the two new admin endpoints (status-overview,
backup/test).
AGENTS.md
- Status block rewritten to reflect what shipped in 1.4.0 vs
what's in flight for 1.4.1.
- File layout: settings monolith replaced by /settings/[section]
routing, admin/page.tsx now the 77-LOC shell, src/components/
settings/ and src/components/admin/ added.
- Removed the stale "Settings Page" gotcha (about non-blocking
set-state-in-effect lint); the rule is strict now.
- Database Models 25 → 26.
CLAUDE.md
- Same model-count and component-folder updates as AGENTS.md.
- Adds Multi-tenant prep and Native API client patterns under
Important Patterns (HEALTHLOG_PROCESS_TYPE, ENCRYPTION_KEYS,
BACKUP_S3_*, refresh-token rotation).
- Lists tests/integration/ and e2e/ in File Layout.
docs/api/openapi.yaml
- Adds 11 new endpoints: GET /api/version, the five test endpoints
(Withings, moodLog, Web Push, Glitchtip, Umami), the two refresh
endpoints, GET /api/admin/status-overview, POST /api/admin/backup/test.
- The bulk of the diff is prettier reformatting that the existing
file had drifted from (single → double quotes throughout YAML);
no semantic change.
docs/migration/v1.3-to-v1.4.md
- Corrects the now-wrong claim that v1.4 ships no migrations
(it ships 0025_refresh_tokens + 0025_user_locale_drift_fix).
- Adds full env-var sections for the Worker/Web split, Encryption
key versioning, and Off-host backup target.
- Documents URL changes (/settings#anchor → /settings/[section]).
- Replaces the "deferred to a future release" list with a
landed-in-v1.4 vs landed-in-v1.4.1 status table.
This commit is contained in:
1 parent
fdf8dd6eb9
commit
ea032c8857
5 files changed
+1719
-1105
No files matched your search
+1492
-999
File diff suppressed because it is too large.
Load diff
+118
-30
@@ -1,11 +1,11 @@
|
||||
# Migrating from HealthLog 1.3 to 1.4
|
||||
|
||||
Both 1.3.x and 1.4.0 use Prisma migrations 0001–0024 and the same
|
||||
PostgreSQL schema. The upgrade is **drop-in for self-hosters running
|
||||
the GHCR image** — no manual migration step beyond the standard
|
||||
`docker compose pull && docker compose up -d`. This guide documents
|
||||
what changes for operators and integrators, in case you're extending
|
||||
the API.
|
||||
v1.4.0 is **drop-in for self-hosters running the GHCR image** — the
|
||||
two new migrations (`0025_refresh_tokens`, `0025_user_locale_drift_fix`)
|
||||
both apply on container start via `prisma migrate deploy`, and every
|
||||
new env var in §Environment variables below has a safe default. This
|
||||
guide documents what changes for operators and integrators, in case
|
||||
you're extending the API or scaling the deployment.
|
||||
|
||||
## TL;DR
|
||||
|
||||
@@ -14,25 +14,83 @@ docker compose pull
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
That's it. No DB migration to apply, no env vars to add, no breaking
|
||||
API change.
|
||||
That's it. The migrations are forward-compatible (`IF NOT EXISTS`
|
||||
guards), no env vars are _required_ to be added, and no API contract
|
||||
changes shape or status code.
|
||||
|
||||
## Database
|
||||
|
||||
- Prisma schema unchanged from 1.3.3. Migrations 0001–0024 remain
|
||||
authoritative. v1.4.0 brings no new migration files.
|
||||
- **`0025_refresh_tokens`** _(new)_ — adds the `refresh_tokens` table
|
||||
for the native-client 24h access-token / refresh-token rotation
|
||||
flow. Browser cookie sessions don't use it.
|
||||
- **`0025_user_locale_drift_fix`** _(new)_ — `ADD COLUMN IF NOT
|
||||
EXISTS users.locale TEXT` to backfill an environment that was kept
|
||||
in sync via `prisma db push` rather than `migrate deploy`. No-op
|
||||
on installations that were already current.
|
||||
- Both migrations are idempotent. A rollback to 1.3.3 keeps the
|
||||
schema usable; the dropped tables/columns are simply unused.
|
||||
|
||||
## Environment variables
|
||||
|
||||
- **`NEXT_PUBLIC_APP_BUILD_SHA`** *(optional, new)* — the short Git
|
||||
SHA of the build, surfaced through `/api/version` so the future
|
||||
About surface can render it. The `docker-publish` workflow can wire
|
||||
this once the About UI lands.
|
||||
- **`NEXT_PUBLIC_APP_BUILT_AT`** *(optional, new)* — ISO-8601 build
|
||||
timestamp, same plumbing.
|
||||
### About surface
|
||||
|
||||
Neither is required. Local `pnpm dev` returns `null` for both fields
|
||||
and the UI falls back to "development" wording.
|
||||
- **`NEXT_PUBLIC_APP_BUILD_SHA`** _(optional, new)_ — short Git SHA
|
||||
exposed through `/api/version`, rendered on Settings → About.
|
||||
- **`NEXT_PUBLIC_APP_BUILT_AT`** _(optional, new)_ — ISO-8601 build
|
||||
timestamp.
|
||||
|
||||
Both are optional; without them, the About surface renders
|
||||
"development" wording.
|
||||
|
||||
### Worker / web split
|
||||
|
||||
- **`HEALTHLOG_PROCESS_TYPE`** _(optional, default `all`)_ — set to
|
||||
`web` to disable the pg-boss worker (jobs queue but don't run), or
|
||||
`worker` to refuse all HTTP traffic with `503 + X-HealthLog-Process-Type:
|
||||
worker`. Default `all` keeps the single-container behaviour.
|
||||
Only relevant if you're scaling HTTP and the worker independently.
|
||||
|
||||
### Encryption-key versioning
|
||||
|
||||
- **`ENCRYPTION_KEYS`** _(optional, new)_ — JSON object mapping
|
||||
versioned key IDs to 64-char hex keys, e.g. `{"v1": "...", "v2":
|
||||
"..."}`. When present, ciphertexts are written with the
|
||||
`<keyId>.<base64>` format and decrypted by looking up the key ID.
|
||||
Existing 1.3-format ciphertexts (no key prefix) keep decrypting
|
||||
with `ENCRYPTION_KEY` indefinitely.
|
||||
- **`ENCRYPTION_ACTIVE_KEY_ID`** _(optional, new)_ — the key ID used
|
||||
for new writes. Must be a key in `ENCRYPTION_KEYS`. Defaults to
|
||||
the legacy single-key behaviour if either is unset.
|
||||
- **`ENCRYPTION_KEY`** _(unchanged)_ — still honoured as a fallback
|
||||
when `ENCRYPTION_KEYS` is empty. No action needed for existing
|
||||
installs.
|
||||
- Rotation: `pnpm tsx scripts/rotate-encryption-key.ts <newKeyId>`
|
||||
re-encrypts every ciphertext under the new key without downtime.
|
||||
Walk-through in `docs/ops/encryption-key-rotation.md`.
|
||||
|
||||
### Off-host backup target _(optional)_
|
||||
|
||||
If unset, the existing local `DataBackup` storage continues to work.
|
||||
|
||||
- **`BACKUP_S3_ENDPOINT`** — S3-compatible endpoint URL. Leave blank
|
||||
to disable off-host backup.
|
||||
- **`BACKUP_S3_BUCKET`** — destination bucket name.
|
||||
- **`BACKUP_S3_ACCESS_KEY`**, **`BACKUP_S3_SECRET_KEY`** — IAM
|
||||
credentials. Worker only requests `PutObject` + `GetObject` —
|
||||
never `DeleteObject`. Retention is the bucket's lifecycle policy.
|
||||
- **`BACKUP_S3_REGION`** _(default `auto`)_.
|
||||
- **`BACKUP_RETENTION_DAYS`** _(default `30`)_ — surfaced in the
|
||||
admin UI; the lifecycle rule on your bucket is the actual enforcer.
|
||||
- **`BACKUP_ENCRYPTION_KEY`** — separate 64-char hex key for the
|
||||
AES-GCM envelope of each upload. **Keep offline / in a vault.**
|
||||
Lose this and the off-host backups are unreadable.
|
||||
|
||||
### API token hashing _(unchanged but worth re-confirming)_
|
||||
|
||||
- **`API_TOKEN_HMAC_KEY`** — 64-char hex string. Used to HMAC
|
||||
Bearer tokens before storage so a DB leak can't be reversed via
|
||||
rainbow table. Same key now also keys the new `RefreshToken` row
|
||||
hashes. **Do not rotate without invalidating every native client.**
|
||||
|
||||
## API
|
||||
|
||||
@@ -41,6 +99,30 @@ and the UI falls back to "development" wording.
|
||||
- **`GET /api/version`** — public, static, returns
|
||||
`{ version, buildSha, builtAt, license, repository, changelog, docs }`.
|
||||
No authentication.
|
||||
- **`POST /api/integrations/withings/test`** — admin-only probe
|
||||
against the saved Withings OAuth connection. Returns `{ ok, latency_ms }`
|
||||
on success.
|
||||
- **`POST /api/integrations/moodlog/test`** — admin-only HEAD
|
||||
request against `https://moodlog.app/api/health`. SSRF-guarded.
|
||||
- **`POST /api/notifications/web-push/test`** — sends a smoke push
|
||||
notification to the current user's subscribed devices.
|
||||
- **`POST /api/monitoring/glitchtip/test`** — fires a benign event
|
||||
at the configured DSN.
|
||||
- **`POST /api/monitoring/umami/test`** — verifies the script URL +
|
||||
website ID resolve and respond with the expected payload.
|
||||
- **`POST /api/admin/backup/test`** — admin-only round-trip against
|
||||
the configured `BACKUP_S3_*` credentials.
|
||||
- **`GET /api/admin/status-overview`** — admin-only aggregator
|
||||
returning the six-card summary the new admin top strip renders in
|
||||
one batched query.
|
||||
- **`POST /api/auth/refresh`** — native-client refresh-token
|
||||
rotation. Cookie-session browsers don't use this.
|
||||
- **`POST /api/auth/refresh/revoke`** — paired logout-on-device that
|
||||
flips both the refresh row and the matching `ApiToken` row to
|
||||
revoked.
|
||||
|
||||
All new admin endpoints are hidden from anonymous traffic by the
|
||||
proxy and rate-limited.
|
||||
|
||||
### Behaviour-only changes
|
||||
|
||||
@@ -111,21 +193,27 @@ n8n, and Health Connect integrations need no change.
|
||||
8 000–15 000 in the effective-range resolver) now use the same
|
||||
band, anchored on Saint-Maurice et al., JAMA 2020.
|
||||
|
||||
## What's deferred to a future release
|
||||
## URL changes
|
||||
|
||||
The v1.3.3 ecosystem audit identified four architectural rewrites that
|
||||
are intentionally outside v1.4.0:
|
||||
- **Settings has moved to per-section routes.** `/settings#integrations`
|
||||
→ `/settings/integrations`, etc. The legacy `/settings#anchor` URLs
|
||||
still 308-redirect to the new routes; sidebar deep-links and the
|
||||
`<a href="/settings#thresholds">` patterns from 1.3 keep working.
|
||||
|
||||
- Settings page split into per-section routes (`/settings/[section]`).
|
||||
- Admin page redesign with status-first card grid.
|
||||
- AI insights rework with severity-coloured key-findings hero and
|
||||
dynamic chart inclusion via an allowlist token map.
|
||||
- Multi-tenant prep (off-host backups, encryption-key versioning,
|
||||
worker/web container split, native-Bearer User-Agent gating).
|
||||
- Postgres-backed integration test suite (Testcontainers).
|
||||
## What landed in v1.4 vs v1.4.1
|
||||
|
||||
These ride a future release; the v1.4 marathon closed every CRIT and
|
||||
HIGH the audit identified except those four.
|
||||
The v1.3.3 ecosystem audit identified architectural rewrites tracked
|
||||
through v1.4. Status as of the v1.4.1 cycle:
|
||||
|
||||
| Bucket | Status |
|
||||
| -------------------------------------------------------------------------------------- | ------------------- |
|
||||
| Settings page split into `/settings/[section]` | ✓ shipped in v1.4.0 |
|
||||
| Admin status-first card grid + aggregator endpoint | ✓ shipped in v1.4.0 |
|
||||
| AI insights rework — severity hero + allowlisted inline charts | ✓ shipped in v1.4.0 |
|
||||
| Multi-tenant prep (off-host backups, key versioning, worker/web split, refresh tokens) | ✓ shipped in v1.4.0 |
|
||||
| Per-section admin component extraction (inner monolith → one file per panel) | ✓ shipped in v1.4.1 |
|
||||
| Postgres-backed integration test suite (testcontainers) | ✓ shipped in v1.4.1 |
|
||||
| Playwright + axe-core E2E foundation | ✓ shipped in v1.4.1 |
|
||||
|
||||
## Rollback
|
||||
|
||||
|
||||
Reference in new issue
Block a user