mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 13:01:00 +00:00
docs: sync README/AGENTS/CONTRIBUTING/CLAUDE/SECURITY to v1.3.2 reality
Full audit of every overlapping claim across the five top-level docs
against the v1.3.2 codebase. Fixes structural drift accumulated since
v1.2:
- README: API envelope was documented as `{ data, error, meta }` but the
actual helpers return `{ data, error }`. Architecture tree was missing
6 src/app/, 4 components/, 8 lib/ subdirectories that landed in
1.2/1.3 (auth, mood, charts, targets, notifications, bugreport,
gamification, settings, ai, feedback, insights, logging, moodlog,
monitoring, …). API Reference grew 4 new sections (Personalization,
Feedback + Tokens, Notifications, Admin) covering ~25 previously
undocumented endpoints. Route count `~60` → `100+`. Achievement count
`30+` → `38+`. i18n keys `1000+` → `1500+` with note about the new
integrity test.
- AGENTS.md: Status `v1.2.0` → `v1.3.2` with the body-composition / SSRF
/ GHCR / pg-boss-drain / blocking-CI / locale-integrity highlights.
Prisma `7.4` → `7.8`. Migrations `0001–0018` → `0001–0022`. Settings
page `13 sections / ~2100 lines` → `8 top-level sections / ~3150
lines` with the actual section IDs. Insights page line estimate
trimmed to `~1750`, section ID `medications` → `meds`.
NotificationChannel / EventType correctly described as `String`
fields (not Prisma enums) sourced from
`src/lib/notifications/types.ts`.
- CONTRIBUTING.md: UI-language statement was inverted ("UI text in
German" → English-default with German user-selectable, plus the
i18n integrity test). Dark-mode-only claim corrected — light/system
toggle exists in the topbar. Node `22+` → `20+` to match the README.
openssl recipe split: POSTGRES_PASSWORD uses base64 24, the three
hex secrets use hex 32. CI check list expanded to the 5-step
pipeline (typecheck, lint, test, format:check, build).
- CLAUDE.md: vitest config path `vitest.config.ts` → `vitest.config.mts`.
Bearer-token hashing labelled `HMAC-SHA256` (keyed by
`API_TOKEN_HMAC_KEY`) instead of plain SHA-256. Removed the
reference to a non-existent `docs/STATUS.md` and the overstated
`docs/{architecture,security,ops,API,ADRs}` directory list — the
long-form end-user docs live at docs.healthlog.dev, only audit notes
are local.
- SECURITY.md: pin example bumped from `:1.2.0` to `:1.3.2`.
Verified against code: 23 Prisma models, all listed endpoints exist,
all package.json versions match, every CHANGELOG v1.3.x claim
(SSRF guard, Withings 77/88 mapping, pg-boss SIGTERM drain, WCAG
44×44 touch targets, rate-limited threshold writes, N+1 fix in
/api/insights/comprehensive) traced to the actual implementation.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
c584ead9c8
commit
0783261b44
5 files changed
+162
-53
No files matched your search
@@ -6,14 +6,14 @@ Instructions for AI coding agents (OpenAI Codex, Claude Code, Cursor, etc.) work
|
||||
|
||||
**HealthLog** — a personal health-tracking web app (weight, blood pressure, pulse, mood, medication compliance) with Withings integration, moodLog.app sync, Dracula-themed UI, mobile-first PWA design.
|
||||
|
||||
**Status**: v1.2.0 (Custom Thresholds, Blood Glucose, Dashboard Customization, Built-in Feedback, Multi-Provider AI). See GitHub Issues for open tasks.
|
||||
**Status**: v1.3.2 — Body composition (Total Body Water + Bone Mass), SSRF-hardened outbound fetches, GHCR multi-arch images (`linux/amd64` + `linux/arm64`) with SLSA provenance + SBOM, pg-boss graceful SIGTERM drain, blocking TypeScript CI, locale-integrity test guard. See GitHub Releases + CHANGELOG.md for the full feature timeline (v1.0 → v1.3).
|
||||
|
||||
## Tech Stack
|
||||
|
||||
| Layer | Technology | Version | Notes |
|
||||
| --------------- | -------------------- | ------- | ----------------------------------------------------------------------- |
|
||||
| Framework | Next.js (App Router) | 16 | TypeScript strict, RSC default, `"use client"` only for interactivity |
|
||||
| ORM | Prisma | 7.4 | Uses `PrismaPg` adapter, **not** `url` in schema — see gotchas below |
|
||||
| ORM | Prisma | 7.8 | Uses `PrismaPg` adapter, **not** `url` in schema — see gotchas below |
|
||||
| Database | PostgreSQL | 16 | Docker Compose service, port 5432, user `healthlog` |
|
||||
| UI | shadcn/ui (new-york) | latest | Components in `src/components/ui/` |
|
||||
| Theme | Dracula | — | CSS variables in `globals.css`, dark mode default, `--dracula-*` tokens |
|
||||
@@ -76,10 +76,10 @@ src/
|
||||
│ ├── medications/page.tsx # Medications management
|
||||
│ ├── notifications/page.tsx # Notification preferences matrix
|
||||
│ ├── onboarding/page.tsx # 4-step guided onboarding
|
||||
│ ├── settings/page.tsx # All settings (13 sections, ~2100 lines)
|
||||
│ ├── settings/page.tsx # All settings (8 top-level sections, ~3150 lines — split tracked for 1.4.0)
|
||||
│ ├── mood/page.tsx # Mood tracking
|
||||
│ ├── targets/page.tsx # Target values dashboard
|
||||
│ └── api/ # ~60 API route files (see docs/api.md)
|
||||
│ └── api/ # 100+ API route files (admin, auth, measurements, medications, mood, insights, integrations, ingest, dashboard, feedback, tokens, notifications, monitoring, …)
|
||||
│ ├── mood-entries/ # Mood CRUD
|
||||
│ ├── import/ # JSON data import
|
||||
│ ├── doctor-report/ # Doctor report data aggregation
|
||||
@@ -93,7 +93,9 @@ src/
|
||||
│ ├── measurements/ # Measurement form, list
|
||||
│ ├── mood/ # Mood form, mood list
|
||||
│ ├── charts/ # Recharts wrappers, compliance charts
|
||||
│ ├── insights/ # AI insights card
|
||||
│ ├── insights/ # AI insights cards (status, advisor)
|
||||
│ ├── gamification/ # Achievement cards, progress
|
||||
│ ├── settings/ # Settings-page section components
|
||||
│ └── monitoring/ # Umami, GlitchTip bootstrap
|
||||
├── lib/
|
||||
│ ├── db.ts # Prisma client singleton
|
||||
@@ -109,6 +111,13 @@ src/
|
||||
│ ├── notifications/ # Dispatcher, types, senders (telegram, ntfy, web-push)
|
||||
│ ├── jobs/ # pg-boss worker (reminders, insights, backups)
|
||||
│ ├── validations/ # Zod schemas (shared between API + client)
|
||||
│ ├── ai/ # Multi-provider client (OpenAI, Anthropic, local OpenAI-compat)
|
||||
│ ├── feedback/ # In-app feedback + optional GitHub escalation
|
||||
│ ├── gamification/ # Achievement definitions + progress
|
||||
│ ├── insights/ # Insight pipeline + prompts
|
||||
│ ├── logging/ # Wide Events: builder, context, sampler, transports, background
|
||||
│ ├── moodlog/ # moodLog.app webhook + sync
|
||||
│ ├── monitoring/ # Umami / GlitchTip server-side hooks
|
||||
│ └── withings/ # Withings OAuth client + sync service
|
||||
├── hooks/
|
||||
│ └── use-auth.ts # useAuth(), useLogout() hooks
|
||||
@@ -118,7 +127,7 @@ messages/
|
||||
└── en.json # English translations
|
||||
prisma/
|
||||
├── schema.prisma # Database schema (23 models)
|
||||
└── migrations/ # Migration files (0001–0018)
|
||||
└── migrations/ # Migration files (0001–0022; latest: body_composition_metrics)
|
||||
prisma.config.ts # Prisma config (DB URL lives here, NOT in schema)
|
||||
public/
|
||||
├── sw.js # Service worker (Web Push + offline caching)
|
||||
@@ -167,15 +176,15 @@ These are hard-won lessons. Ignoring them will cause errors:
|
||||
|
||||
### Settings Page
|
||||
|
||||
- One large file (~2100 lines), 13 sections. Sidebar switches to "settings mode" showing section shortcuts.
|
||||
- One large file (~3150 lines), 8 top-level sections. Sidebar switches to "settings mode" showing section shortcuts. Splitting into per-section files is tracked for 1.4.0 — until then, ESLint `react-hooks/set-state-in-effect` stays non-blocking because of the long-standing violations in this file.
|
||||
- Sections scroll-to with highlight animation (`section-highlight` CSS class).
|
||||
- Section IDs: `profil`, `sprache`, `sicherheit`, `telegram`, `ntfy`, `web-push`, `insights`, `withings`, `api`, `export`, `protokoll`, `daten`.
|
||||
- Top-level section IDs: `section-allgemein`, `section-sicherheit`, `section-benachrichtigungen`, `section-personalization`, `section-integration`, `section-api`, `section-export`, `section-danger-zone`. Sub-anchors inside those sections include `profil`, `passwort`, `passkeys`, `telegram`, `ntfy`, `web-push`, `insights`, `dashboard-layout`, `thresholds`, `withings`, `moodlog`, `api-tokens`, `api-endpoints`.
|
||||
|
||||
### Insights Page
|
||||
|
||||
- Large file (~1800+ lines), 7 content sections with AI summaries.
|
||||
- Large file (~1750 lines), 7 content sections with AI summaries.
|
||||
- Sticky horizontal chip navigation (`InsightsSectionNav` component) with IntersectionObserver for active state tracking.
|
||||
- Section IDs: `general`, `bp`, `weight`, `pulse`, `mood`, `medications`, `bmi`.
|
||||
- Section IDs: `general`, `bp`, `weight`, `pulse`, `mood`, `meds`, `bmi`.
|
||||
- Each section has `scroll-mt-28` for header offset on scroll.
|
||||
|
||||
### Sidebar
|
||||
@@ -192,8 +201,8 @@ These are hard-won lessons. Ignoring them will cause errors:
|
||||
|
||||
### Notification System
|
||||
|
||||
- **Channels**: `TELEGRAM`, `NTFY`, `WEB_PUSH` (DB: `NotificationChannel`).
|
||||
- **Event types**: `MEDICATION_REMINDER`, `MEASUREMENT_ANOMALY`, `COMPLIANCE_LOW`, `WITHINGS_SYNC_FAILED`, `SYSTEM_ALERT`.
|
||||
- **Channels**: `telegram`, `ntfy`, `web_push` — stored as plain `String` on `NotificationChannel.type` (no Prisma enum; the canonical list lives in `src/lib/notifications/types.ts`).
|
||||
- **Event types**: `medication_reminder`, `measurement_anomaly`, `compliance_low`, `withings_sync_failed`, `system_alert` — also `String` on `NotificationPreference.eventType`. Source of truth is the discriminated union in `src/lib/notifications/types.ts`.
|
||||
- **Opt-out model**: Preferences default to ON (enabled) when no `NotificationPreference` row exists.
|
||||
- **Dispatcher**: `src/lib/notifications/dispatcher.ts` checks channel enabled + preference per event type.
|
||||
- **Telegram**: Inline buttons (Take/Skip/Snooze 1h/Snooze 3h), pre-end window reminders (30 min before), message auto-cleanup after 24h.
|
||||
|
||||
@@ -44,7 +44,7 @@ docker compose logs -f app # Tail app logs
|
||||
- **API response envelope**: `{ data, error, meta }` via helpers in `src/lib/api-response.ts`.
|
||||
- **apiHandler** wraps ALL API route handlers (`src/lib/api-handler.ts`) — error handling, Wide Event logging, x-request-id propagation.
|
||||
- **Structured Logging** (Wide Events) in `src/lib/logging/` — one JSON event per request/operation via `WideEventBuilder` + `AsyncLocalStorage`. Tail sampling, stdout JSON + optional Loki Push.
|
||||
- **Vitest** for unit testing. Config in `vitest.config.ts`.
|
||||
- **Vitest** for unit testing. Config in `vitest.config.mts`.
|
||||
- **pg-boss** (PostgreSQL-native) for job queue: medication reminders, insight caching, weekly data backups.
|
||||
- **jsPDF** + jspdf-autotable for client-side doctor report PDF generation (`src/lib/doctor-report-pdf.ts`).
|
||||
- **PWA offline** via service worker caching strategies in `public/sw.js` (cache-first for static, network-first for pages, network-only for API).
|
||||
@@ -56,7 +56,7 @@ docker compose logs -f app # Tail app logs
|
||||
- Timezone: `Europe/Berlin` for display, UTC in database.
|
||||
- Sensitive data (Withings tokens, API keys, VAPID private keys) encrypted with AES-256-GCM (`src/lib/crypto.ts`) before DB storage.
|
||||
- Passkeys are primary auth (SimpleWebAuthn v13). Sessions stored server-side in PostgreSQL.
|
||||
- All API mutations require authentication. External ingest uses Bearer token (hashed with SHA-256).
|
||||
- All API mutations require authentication. External ingest uses Bearer token (hashed with HMAC-SHA256 keyed by `API_TOKEN_HMAC_KEY`).
|
||||
- Rate limiting (in-memory sliding window) on auth and external-facing endpoints.
|
||||
|
||||
## File Layout
|
||||
@@ -84,9 +84,9 @@ docker compose logs -f app # Tail app logs
|
||||
- `prisma/schema.prisma` — database schema (23 models)
|
||||
- `prisma.config.ts` — Prisma config (DB URL here, not in schema)
|
||||
- `public/sw.js` — Service worker for Web Push notifications + offline caching
|
||||
- `docs/` — architecture, security, assumptions, ops, API docs, ADRs
|
||||
- `docs/STATUS.md` — Current project status + open tasks
|
||||
- `docs/` — long-form audit notes (`docs/audit/`); end-user docs live in the separate site at https://docs.healthlog.dev
|
||||
- `AGENTS.md` — AI agent instructions (Codex, Cursor, etc.)
|
||||
- `CHANGELOG.md` — release notes per semver tag
|
||||
|
||||
## Important Patterns
|
||||
|
||||
|
||||
+29
-16
@@ -4,7 +4,7 @@ Contributions are welcome. This guide covers how to set up the project and submi
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Node.js 22+
|
||||
- Node.js 20+
|
||||
- pnpm
|
||||
- PostgreSQL 16+ (or Docker)
|
||||
- Git
|
||||
@@ -20,13 +20,21 @@ cp .env.example .env
|
||||
Edit `.env` and configure at minimum:
|
||||
|
||||
```
|
||||
DATABASE_URL="postgresql://healthlog:healthlog@localhost:5432/healthlog"
|
||||
POSTGRES_PASSWORD=<base64, 24 bytes>
|
||||
DATABASE_URL="postgresql://healthlog:${POSTGRES_PASSWORD}@db:5432/healthlog"
|
||||
SESSION_SECRET=<64-char hex>
|
||||
ENCRYPTION_KEY=<64-char hex>
|
||||
API_TOKEN_HMAC_KEY=<64-char hex>
|
||||
```
|
||||
|
||||
Generate secrets with `openssl rand -hex 32`.
|
||||
Generate the four secrets:
|
||||
|
||||
```bash
|
||||
echo "POSTGRES_PASSWORD=$(openssl rand -base64 24)" >> .env
|
||||
echo "SESSION_SECRET=$(openssl rand -hex 32)" >> .env
|
||||
echo "ENCRYPTION_KEY=$(openssl rand -hex 32)" >> .env
|
||||
echo "API_TOKEN_HMAC_KEY=$(openssl rand -hex 32)" >> .env
|
||||
```
|
||||
|
||||
### With Docker (database only)
|
||||
|
||||
@@ -47,23 +55,28 @@ docker compose up -d
|
||||
## Development Workflow
|
||||
|
||||
```bash
|
||||
pnpm dev # Start dev server (http://localhost:3000)
|
||||
pnpm lint # ESLint
|
||||
pnpm format # Prettier
|
||||
pnpm typecheck # TypeScript strict mode
|
||||
pnpm test # Vitest
|
||||
pnpm dev # Start dev server (http://localhost:3000)
|
||||
pnpm lint # ESLint
|
||||
pnpm format:check # Prettier (check)
|
||||
pnpm typecheck # TypeScript strict mode
|
||||
pnpm test # Vitest
|
||||
pnpm build # Next.js production build
|
||||
```
|
||||
|
||||
All four checks must pass before submitting a PR.
|
||||
All five checks must pass before submitting a PR. The full one-liner that mirrors CI:
|
||||
|
||||
```bash
|
||||
pnpm typecheck && pnpm lint && pnpm test && pnpm format:check && pnpm build
|
||||
```
|
||||
|
||||
## Code Conventions
|
||||
|
||||
- **TypeScript strict mode** -- no `any` types, no type assertions unless absolutely necessary
|
||||
- **UI text in German**, code/comments/docs in English
|
||||
- **API responses** follow `{ data, error, meta }` envelope pattern
|
||||
- **Zod v4** for input validation (API routes and forms)
|
||||
- **shadcn/ui** components (new-york style) for UI primitives
|
||||
- **Dracula theme** -- dark mode only, use `--dracula-*` CSS tokens
|
||||
- **TypeScript strict mode** -- avoid `any`. Where it's truly unavoidable (e.g. variadic Next.js handler signatures in `src/lib/api-handler.ts`), document the reason inline.
|
||||
- **English-default UI** -- the default locale is English. German is user-selectable. Code, comments, commit messages, and docs are English. All user-facing strings go through `t("key")` with translations in both `messages/en.json` and `messages/de.json`. The `i18n-locale-integrity.test.ts` suite blocks merges if keys drift between locales or duplicate at any nesting depth.
|
||||
- **API responses** follow the `{ data, error }` envelope via `apiSuccess()` / `apiError()` in `src/lib/api-response.ts`. Wrap every route handler in `apiHandler()` (`src/lib/api-handler.ts`) for error handling, structured Wide-Event logging, and `x-request-id` propagation.
|
||||
- **Zod v4** (`import { ... } from "zod/v4"`) for input validation in API routes and forms.
|
||||
- **shadcn/ui** components (new-york style) for UI primitives.
|
||||
- **Dracula theme** -- dark mode is the default; a `light`/`system` toggle is exposed in the topbar. Chart and accent colors use the `--dracula-*` CSS tokens so both themes stay coherent.
|
||||
|
||||
See `CLAUDE.md` for detailed architecture and patterns.
|
||||
|
||||
@@ -82,7 +95,7 @@ Always include the migration file in your PR.
|
||||
1. Fork the repository
|
||||
2. Create a feature branch (`git checkout -b feature/your-feature`)
|
||||
3. Make your changes
|
||||
4. Ensure all checks pass (`pnpm lint && pnpm typecheck && pnpm test`)
|
||||
4. Ensure all checks pass (`pnpm typecheck && pnpm lint && pnpm test && pnpm format:check && pnpm build`)
|
||||
5. Submit a PR with a clear description of the changes
|
||||
|
||||
## Security
|
||||
|
||||
@@ -59,9 +59,9 @@ Most health apps lock your data behind proprietary clouds, push subscriptions, a
|
||||
|
||||
**Multi-Channel Notifications** -- Telegram (with inline action buttons), ntfy (self-hostable), and Web Push. Medication reminders with late/missed escalation.
|
||||
|
||||
**Gamification** -- 30+ persistent achievements across intake streaks, compliance milestones, and healthy metric streaks.
|
||||
**Gamification** -- 38+ persistent achievements across intake streaks, compliance milestones, and healthy metric streaks.
|
||||
|
||||
**Internationalization** -- English (default) and German UI with 1000+ translation keys. Numbers, dates, units, and AI prompts all locale-aware via `useFormatters()`. Browser-based detection with per-user override.
|
||||
**Internationalization** -- English (default) and German UI with 1500+ translation keys, guarded by a CI integrity test that fails the build on duplicate keys or drift between locales. Numbers, dates, units, and AI prompts all locale-aware via `useFormatters()`. Browser-based detection with per-user override.
|
||||
|
||||
---
|
||||
|
||||
@@ -163,30 +163,50 @@ Telegram bot token, ntfy settings, Web Push VAPID keys, Umami, and GlitchTip URL
|
||||
```
|
||||
src/
|
||||
├── app/ # Next.js App Router pages & API routes
|
||||
│ ├── api/ # REST API endpoints (~60 route files)
|
||||
│ ├── api/ # REST API endpoints (100+ route files)
|
||||
│ ├── admin/ # Admin panel
|
||||
│ ├── auth/ # Login, register, passkey enrolment
|
||||
│ ├── medications/ # Medication management
|
||||
│ ├── measurements/ # Health metric entry
|
||||
│ ├── mood/ # Mood log
|
||||
│ ├── insights/ # AI-powered analytics
|
||||
│ ├── charts/ # Long-form charts
|
||||
│ ├── achievements/ # Gamification page
|
||||
│ ├── targets/ # Custom thresholds dashboard
|
||||
│ ├── notifications/ # Notification preferences matrix
|
||||
│ ├── bugreport/ # Built-in feedback / bug report
|
||||
│ ├── onboarding/ # 4-step guided setup
|
||||
│ └── settings/ # User preferences
|
||||
│ └── settings/ # User preferences (8 top-level sections)
|
||||
├── components/
|
||||
│ ├── ui/ # shadcn/ui primitives
|
||||
│ ├── layout/ # Shell (sidebar, topbar, bottom nav)
|
||||
│ ├── medications/ # Medication cards, forms, timeline
|
||||
│ ├── measurements/ # Measurement form, list
|
||||
│ ├── mood/ # Mood form, mood list
|
||||
│ └── charts/ # Recharts wrappers
|
||||
│ ├── charts/ # Recharts wrappers
|
||||
│ ├── insights/ # AI insight status / advisor cards
|
||||
│ ├── gamification/ # Achievement cards, progress
|
||||
│ ├── monitoring/ # Umami / GlitchTip bootstrap
|
||||
│ └── settings/ # Settings-page section components
|
||||
├── lib/
|
||||
│ ├── auth/ # Session, audit, passkey logic
|
||||
│ ├── notifications/ # Dispatcher + channel senders
|
||||
│ ├── jobs/ # pg-boss worker
|
||||
│ ├── analytics/ # Trend calculations, compliance
|
||||
│ ├── jobs/ # pg-boss worker (reminders, insights, backups)
|
||||
│ ├── analytics/ # Trend calculations, compliance, correlations
|
||||
│ ├── ai/ # Multi-provider client (OpenAI, Anthropic, local)
|
||||
│ ├── insights/ # Insight pipeline + medical prompts
|
||||
│ ├── gamification/ # Achievement definitions
|
||||
│ ├── feedback/ # Built-in feedback + GitHub escalation
|
||||
│ ├── moodlog/ # moodLog.app webhook + sync
|
||||
│ ├── monitoring/ # Umami / GlitchTip server-side hooks
|
||||
│ ├── withings/ # OAuth client, sync service
|
||||
│ ├── logging/ # Wide Events: builder, context, transports
|
||||
│ ├── i18n/ # Translations context & config
|
||||
│ ├── validations/ # Shared Zod schemas
|
||||
│ ├── api-handler.ts # apiHandler wrapper, requireAuth/requireAdmin
|
||||
│ ├── api-response.ts # { data, error } envelope helpers
|
||||
│ ├── crypto.ts # AES-256-GCM encrypt/decrypt
|
||||
│ ├── rate-limit.ts # Sliding-window rate limiter
|
||||
│ ├── db.ts # Prisma singleton
|
||||
│ └── doctor-report-pdf.ts # Client-side PDF generation
|
||||
├── hooks/ # React hooks
|
||||
@@ -196,10 +216,11 @@ src/
|
||||
### Key Patterns
|
||||
|
||||
- **RSC by default** -- `"use client"` only for interactive components
|
||||
- **API envelope** -- All responses follow `{ data, error, meta }` shape
|
||||
- **API envelope** -- All responses follow `{ data, error }` shape via `apiSuccess()` / `apiError()` in `src/lib/api-response.ts`
|
||||
- **apiHandler wrapper** -- Every API route wraps its handler in `apiHandler()` (`src/lib/api-handler.ts`) for consistent error handling, Wide-Event structured logging, and `x-request-id` propagation
|
||||
- **Encrypted secrets** -- Withings tokens, API keys, VAPID keys, notification credentials
|
||||
- **Timezone-aware** -- `Europe/Berlin` for display, UTC in database
|
||||
- **Route protection** -- `proxy.ts` checks session cookie, redirects unauthenticated requests
|
||||
- **Route protection** -- `proxy.ts` (Next.js 16's renamed middleware) checks session cookie, redirects unauthenticated requests
|
||||
- **Client-side PDF** -- Doctor reports generated in browser via jsPDF
|
||||
|
||||
---
|
||||
@@ -254,17 +275,83 @@ All mutations require authentication via session cookie. External ingest uses Be
|
||||
<details>
|
||||
<summary><strong>Auth and Integrations</strong></summary>
|
||||
|
||||
| Method | Endpoint | Description |
|
||||
| ------ | -------------------------------- | ----------------------- |
|
||||
| `POST` | `/api/auth/register` | Create account |
|
||||
| `POST` | `/api/auth/login` | Password login |
|
||||
| `POST` | `/api/auth/logout` | Destroy session |
|
||||
| `GET` | `/api/auth/me` | Current user profile |
|
||||
| `POST` | `/api/auth/passkey/*` | WebAuthn flows |
|
||||
| `GET` | `/api/withings/connect` | Initiate Withings OAuth |
|
||||
| `POST` | `/api/insights/generate` | Regenerate AI insights |
|
||||
| `GET` | `/api/gamification/achievements` | Achievement progress |
|
||||
| `GET` | `/api/health` | Docker health check |
|
||||
| Method | Endpoint | Description |
|
||||
| ------ | -------------------------------- | ------------------------------------ |
|
||||
| `POST` | `/api/auth/register` | Create account |
|
||||
| `POST` | `/api/auth/login` | Password login |
|
||||
| `POST` | `/api/auth/logout` | Destroy session |
|
||||
| `GET` | `/api/auth/me` | Current user profile + Gravatar URL |
|
||||
| `POST` | `/api/auth/password` | Change password |
|
||||
| `PATCH`| `/api/auth/profile` | Update profile fields |
|
||||
| `POST` | `/api/auth/passkey/*` | WebAuthn flows (4 sub-routes) |
|
||||
| `GET` | `/api/auth/passkeys` | List enrolled passkeys |
|
||||
| `GET` | `/api/auth/codex/authorize` | ChatGPT (codex) OAuth start |
|
||||
| `GET` | `/api/withings/connect` | Initiate Withings OAuth |
|
||||
| `POST` | `/api/withings/sync` | Trigger manual Withings sync |
|
||||
| `POST` | `/api/withings/webhook` | Withings notification webhook |
|
||||
| `POST` | `/api/insights/generate` | Regenerate AI insights |
|
||||
| `GET` | `/api/insights/comprehensive` | Aggregated insight payload |
|
||||
| `GET` | `/api/gamification/achievements` | Achievement progress |
|
||||
| `GET` | `/api/health` | Docker health check |
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>Personalization (Thresholds + Dashboard)</strong></summary>
|
||||
|
||||
| Method | Endpoint | Description |
|
||||
| -------- | ------------------------- | --------------------------------------------- |
|
||||
| `GET` | `/api/user/thresholds` | Read per-user threshold overrides |
|
||||
| `PUT` | `/api/user/thresholds` | Upsert thresholds (rate-limited, audit-logged)|
|
||||
| `GET` | `/api/insights/targets` | Effective ranges (defaults + overrides merged)|
|
||||
| `GET` | `/api/dashboard/widgets` | Read dashboard layout |
|
||||
| `PUT` | `/api/dashboard/widgets` | Persist dashboard layout (show/hide/reorder) |
|
||||
| `POST` | `/api/onboarding/complete`| Mark onboarding finished |
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>Feedback + API Tokens</strong></summary>
|
||||
|
||||
| Method | Endpoint | Description |
|
||||
| -------- | --------------------------------------- | ------------------------------------ |
|
||||
| `POST` | `/api/feedback` | Submit in-app feedback |
|
||||
| `GET` | `/api/bugreport/status` | Check published GitHub issue state |
|
||||
| `GET` | `/api/tokens` | List own API tokens |
|
||||
| `POST` | `/api/tokens` | Mint new API token (Bearer, hashed) |
|
||||
| `DELETE` | `/api/tokens/:id` | Revoke API token |
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>Notifications</strong></summary>
|
||||
|
||||
| Method | Endpoint | Description |
|
||||
| -------- | --------------------------------- | -------------------------------------- |
|
||||
| `GET` | `/api/notifications/preferences` | Read per-channel × per-event matrix |
|
||||
| `PUT` | `/api/notifications/preferences` | Update preferences |
|
||||
| `GET` | `/api/notifications/vapid` | VAPID public key for Web Push |
|
||||
| `POST` | `/api/notifications/web-push` | Register Web Push subscription |
|
||||
| `POST` | `/api/telegram/webhook` | Telegram bot inline-button callback |
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>Admin (admin role required)</strong></summary>
|
||||
|
||||
| Method | Endpoint | Description |
|
||||
| -------- | --------------------------------- | -------------------------------------- |
|
||||
| `GET` | `/api/admin/status` | System + integration status |
|
||||
| `GET` | `/api/admin/users` | List users |
|
||||
| `POST` | `/api/admin/users/:id/reset-password` | Force password reset |
|
||||
| `GET` | `/api/admin/feedback` | All feedback / bug reports |
|
||||
| `POST` | `/api/admin/feedback/:id/github` | Escalate feedback to GitHub issue |
|
||||
| `GET` | `/api/admin/audit-log` | Audit-log viewer |
|
||||
| `GET` | `/api/admin/ai-settings` | Read shared AI provider config |
|
||||
| `PUT` | `/api/admin/ai-settings` | Update shared AI provider config |
|
||||
| `GET` | `/api/admin/tokens` | All issued API tokens |
|
||||
| `POST` | `/api/admin/notifications/test` | Send test notification |
|
||||
| `GET` | `/api/admin/data` | Data backups + counts |
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
+1
-1
@@ -70,6 +70,6 @@ HealthLog Docker images are built and published from this repository's CI:
|
||||
- **Provenance attestation**: each image carries a [SLSA build provenance](https://slsa.dev/spec/v1.0/provenance) statement linking it back to the GitHub Actions run, the commit SHA, and the workflow definition
|
||||
- **SBOM**: each image includes a [Software Bill of Materials](https://docs.docker.com/build/metadata/attestations/sbom/) you can inspect with `docker buildx imagetools inspect ghcr.io/mbombeck/healthlog:latest --format '{{ json .SBOM }}'`
|
||||
|
||||
To pin to a specific version in production, replace `:latest` with the released tag in your `docker-compose.yml`, e.g. `ghcr.io/mbombeck/healthlog:1.2.0`. Pinning is recommended for self-hosters who want explicit control over upgrades.
|
||||
To pin to a specific version in production, replace `:latest` with the released tag in your `docker-compose.yml`, e.g. `ghcr.io/mbombeck/healthlog:1.3.2`. Pinning is recommended for self-hosters who want explicit control over upgrades.
|
||||
|
||||
If you discover a tampered or unexpected image, please report it as a vulnerability via the email above.
|
||||
Reference in new issue
Block a user