Merge branch 'feat/v125-self-description-docs' into release/v1.25.0

# Conflicts:
#	docs/api/mcp-capabilities.md
This commit is contained in:
Marc-André Bombeck committed 2026-06-28 17:46:40 +02:00
commit fb580f4725
17 files changed
+248 -11

No files matched your search

+7 -2
View File
@@ -28,14 +28,19 @@
HealthLog is a self-hosted health tracking app (PWA + native iOS client) that runs from a single `docker compose up` on a NAS, homelab, or small VPS. It brings weight, blood pressure, pulse, blood glucose, body composition, sleep, mood, menstrual cycle, and medications onto one timeline — synced from the devices you already own — and keeps everything encrypted at rest on hardware you control. No vendor cloud, no subscription, no telemetry.
HealthLog is a personal health record-keeping and wellness tool. It is not a medical device and does not diagnose, treat, cure, or prevent any disease — it helps you log, visualise, and export your own data, and leaves clinical judgement to a clinician.
Try the [live demo](https://demo.healthlog.dev) to see a working install — sign in with `demo` / `demo123demo123`.
## Highlights
- **Every vital on one timeline.** Weight, blood pressure, pulse, glucose, body composition, sleep, SpO₂, mood, and cycle tracking — charted with trends, moving averages, and clinical reference ranges (ESH 2023, ADA 2024), overridable with the targets your clinician set.
- **Every vital on one timeline.** Weight, blood pressure, pulse, glucose, body composition, sleep, SpO₂, respiratory rate, mood, and cycle tracking — charted with trends, moving averages, and clinical reference ranges (ESH 2023, ADA 2024), overridable with the targets your clinician set.
- **Clinical signals, opt-in and additive.** Validated mental-wellbeing self-checks (PHQ-9, GAD-7) that sit beside mood tracking with calm crisis-resource handling, grip strength, a 0–10 pain score, waist and body measurements, and a longevity lab panel — each added through one signal registry, so a new signal wires into charts, correlations, the coach, the FHIR map, and the API at once.
- **Records and the documents you're handed.** Structured allergies and family history (encrypted), lab values you key in or scan, and inbound documents — discharge letters and reports — read to extract the facts they state (values, codes, dates) for you to review and confirm. HealthLog transcribes what a document says; it never interprets or diagnoses from it. (Immunization records are deliberately out of scope.)
- **Context that explains the numbers.** An opt-in environmental module folds weather, daylight, and temperature in as influence signals (winter darkness against mood, heat against blood pressure) using a home location you set, so a pattern has somewhere to point.
- **Your devices, one server.** Withings, WHOOP, Oura and Polar sync over OAuth2, Fitbit connects experimentally over the Fitbit Web API, an Apple Health `export.zip` folds your full history in, and the native iOS app streams HealthKit live. A per-metric source priority decides which reading is canonical when wearables overlap.
- **Medication tracking that tells the truth.** Flexible schedules (weekly injections, weekday-only, intervals, PRN, cyclic), a configurable intake window per dose, and a traceable dose history where every slot reads taken, late, skipped, or missed — the same ledger the compliance rate is computed from, so the percentage can never disagree with the timeline.
- **AI insights you own.** Daily briefing, health scores, correlations, and a conversational coach grounded in your own measurements, with proactive check-ins. Bring your own OpenAI or Anthropic key, or point at a local endpoint (Ollama, LM Studio, vLLM) so nothing leaves your network.
- **AI insights you own.** Daily briefing, health scores, correlations, and a conversational coach grounded in your own measurements, with calm proactive check-ins it suppresses when there's nothing genuine to say. The coach describes your data, never diagnoses. Bring your own OpenAI or Anthropic key, or point at a local endpoint (Ollama, LM Studio, vLLM) so nothing leaves your network.
- **Clinician-ready output.** A doctor-report PDF generated client-side, a read-only HL7 FHIR R4 API, and scoped, time-limited share links you revoke after the visit.
- **Private by construction.** AES-256-GCM encryption at rest with zero-downtime key rotation, passkey login, server-side sessions, strict CSP — and no third-party tracking anywhere.
- **Built to be lived in.** Installable PWA with offline support, medication reminders over APNs, Telegram, ntfy, and Web Push, a sub-second dashboard on years of imported history, English and German end to end.
+18 -4
View File
@@ -28,7 +28,10 @@ them up front):
4. **Data and context only.** The server ships facts; it never returns a
diagnosis, clinical verdict, risk score, or treatment change. The
assistant narrates the facts and leaves clinical judgement to the
user's clinician.
user's clinician. This mirrors HealthLog's project-wide self-description
standard: the app is a personal health record-keeping and wellness tool,
not a medical device, and nothing it surfaces — here or in the UI —
diagnoses or treats.
Discover before fetching: call `list_metrics` (or read the
`healthlog://measurements/inventory` resource) first to see what exists,
@@ -106,7 +109,10 @@ surfaces a signal only when the user has recorded it; `fetch metric:<KEY>`
hydrates it). Each carries its unit and population reference band from the
single signal registry; absence is the usual `{ present: false }`. They
sit off the Coach data inventory by design, so `list_metrics` /
`get_metric_series` do not enumerate them — use the reads above.
`get_metric_series` do not enumerate them — use the reads above. A new
signal is declared once in the in-app signal registry and shows up across
the metric tools, correlations, and the FHIR map together, so the MCP
surface never advertises a signal the record can't return.
The **longevity lab panel** (ApoB, Lp(a), hs-CRP, HbA1c, fasting glucose,
fasting insulin, eGFR, GGT, ferritin, omega-3 index) is reached like any
@@ -118,10 +124,18 @@ curated biomarker catalogue.
**Off the MCP surface by construction.** The PHQ-9 / GAD-7 mental-health
screeners (item content and totals) are excluded from AI / MCP, and the
environmental-context signals (`ENV_*`: temperature, sunshine, daylight,
precipitation, barometric pressure) are off MCP in v1. None of them
resolve through any read tool — they are not on the MCP exposure
precipitation, barometric pressure) are off MCP in v1. The structured
records (allergies, family history) and the inbound-document store are
deliberately not exposed either: the document pipeline extracts facts for
the user to confirm in-app rather than streaming them to a model. None of
them resolve through any read tool — they are not on the MCP exposure
allowlist.
This mirrors HealthLog's project-wide self-description standard: the MCP
surface ships data and context, never a diagnosis, clinical verdict, or
treatment change — the assistant narrates the facts and leaves clinical
judgement to the user's clinician.
## Resources
Read-only context the assistant can attach alongside tool results. Like
+24
View File
@@ -198,6 +198,30 @@ The Coach drawer surfaces a "Local" badge when generation resolves
to the local provider, so users who pinned a local endpoint can see
at a glance that their context stayed on the host.
## What the Coach is — and isn't
The Coach is an informational assistant that works from your own
logged data. It is not a doctor, what it says is not medical advice,
and it does not diagnose, prescribe, or change treatment — those
boundaries are written into its system prompt as safety contracts, not
left to chance. It describes patterns observationally ("your resting
heart rate has been rising over 14 days"), never as a verdict about a
named condition, and it defers diagnosis, dose, and drug-interaction
questions to a healthcare professional. This is HealthLog's
project-wide self-description standard: a personal health
record-keeping and wellness tool, not a medical device. The same
non-diagnostic framing governs the daily briefing, the insights, and
every surface that turns your data into words.
The Coach can also reach out proactively — a calm, once-a-day morning
check-in when there is something genuine to surface (a recovery trend
easing off, blood pressure running a touch high). The nudge is warm
and localized, references the focus by category rather than quoting
your own words back, and stays silent when there is nothing real to
say or when you have engaged the Coach recently. It is an invitation,
never a streak-guilt prompt, and it inherits the same non-diagnostic
boundaries as the chat.
## Caching contract
Two caches sit in front of every provider call so generation budgets
+4
View File
@@ -16,6 +16,10 @@ already installed, longer if a TLS-fronted public hostname is in scope
hold a 1.5 GB upload in `/tmp` while it parses.
- **Outbound HTTPS** to `ghcr.io` (image pulls) plus whichever
integration endpoints you plan to enable (Withings, OpenAI, etc.).
The opt-in environmental-context module additionally reaches
`api.open-meteo.com` for weather and daylight; it stays off until you
enable it and set a home location, and every outbound call goes
through the SSRF-guarded egress wrapper.
- **Optional but recommended:** a reverse proxy that terminates TLS
and forwards to `http://localhost:3000` (Caddy, Traefik, Nginx
Proxy Manager, Coolify, or bare Nginx — see `reverse-proxy.md`).
+9
View File
@@ -7792,5 +7792,14 @@
"saved": "Angabe aktualisiert.",
"discarded": "Dokument verworfen."
}
},
"selfDescription": {
"intendedPurpose": "HealthLog ist ein persönliches Werkzeug zur Gesundheitsdokumentation und zum Wohlbefinden. Es hilft dir, deine eigenen Gesundheitsdaten zu erfassen, zu visualisieren und zu exportieren. Es diagnostiziert, behandelt, heilt oder verhindert keine Krankheit und ist kein Medizinprodukt.",
"coach": "Der Coach arbeitet mit deinen eigenen erfassten Daten. Er ist kein Arzt und gibt keine medizinische Beratung — für Diagnose oder Behandlung wende dich an medizinisches Fachpersonal.",
"insights": "Das sind beschreibende Muster aus deinen eigenen erfassten Daten, keine klinische Beurteilung und keine Diagnose.",
"labs": "Das sind deine eigenen Aufzeichnungen, keine medizinische Diagnose. Referenzbereiche unterscheiden sich je nach Labor und Person — nur deine Ärztin oder dein Arzt kann sie für dich einordnen.",
"medications": "Das erfasst die von dir dokumentierten Medikamente und deine eigene Einnahmetreue. Es beurteilt weder Dosierung noch Wechselwirkungen und ist keine medizinische Beratung — kläre das mit Apotheke oder Arztpraxis.",
"emergency": "Falls das ein Notfall sein könnte, wende dich jetzt an deine örtliche Notrufnummer oder an eine ärztliche Stelle. HealthLog kann im Notfall nicht helfen.",
"dataPosture": "HealthLog wird selbst gehostet: Deine Gesundheitsdaten bleiben auf deiner eigenen Instanz und sind im Ruhezustand verschlüsselt. KI-Funktionen nutzen einen von dir mitgebrachten Anbieter-Schlüssel oder ein lokales Modell — nichts verlässt deine Instanz über den von dir konfigurierten Anbieter hinaus, und es gibt keine Drittanbieter-Analyse deiner Gesundheitsdaten."
}
}
+9
View File
@@ -7792,5 +7792,14 @@
"saved": "Fact updated.",
"discarded": "Document discarded."
}
},
"selfDescription": {
"intendedPurpose": "HealthLog is a personal health record-keeping and wellness tool. It helps you log, visualise, and export your own health data. It does not diagnose, treat, cure, or prevent any disease, and it is not a medical device.",
"coach": "The Coach works from your own logged data. It isn't a doctor and doesn't give medical advice — for diagnosis or treatment, talk to a healthcare professional.",
"insights": "These are descriptive patterns computed from your own logged data, not a clinical assessment or diagnosis.",
"labs": "These are your own records, not a medical diagnosis. Reference ranges vary by lab and person — only your clinician can interpret them for you.",
"medications": "This tracks the medications you log and your own adherence. It doesn't assess dosing or interactions and isn't medical advice — confirm those with a pharmacist or doctor.",
"emergency": "If this might be an emergency, contact your local emergency number or a clinician now. HealthLog can't help in an emergency.",
"dataPosture": "HealthLog is self-hosted: your health data stays on your own instance, encrypted at rest. AI features use a provider key you bring or a local model, so nothing leaves your instance beyond the provider you configure, and there is no third-party analytics on your health data."
}
}
+9
View File
@@ -7792,5 +7792,14 @@
"saved": "Dato actualizado.",
"discarded": "Documento descartado."
}
},
"selfDescription": {
"intendedPurpose": "HealthLog es una herramienta personal de registro de salud y bienestar. Te ayuda a registrar, visualizar y exportar tus propios datos de salud. No diagnostica, trata, cura ni previene ninguna enfermedad, y no es un producto sanitario.",
"coach": "El Coach trabaja con tus propios datos registrados. No es un médico y no da consejo médico: para un diagnóstico o tratamiento, consulta a un profesional sanitario.",
"insights": "Son patrones descriptivos calculados a partir de tus propios datos registrados, no una evaluación clínica ni un diagnóstico.",
"labs": "Son tus propios registros, no un diagnóstico médico. Los rangos de referencia varían según el laboratorio y la persona: solo tu médico puede interpretarlos por ti.",
"medications": "Esto registra los medicamentos que anotas y tu propia adherencia. No evalúa dosis ni interacciones y no es consejo médico: confírmalo con tu farmacéutico o médico.",
"emergency": "Si esto pudiera ser una emergencia, llama ahora a tu número de emergencias local o a un profesional sanitario. HealthLog no puede ayudar en una emergencia.",
"dataPosture": "HealthLog es autoalojado: tus datos de salud permanecen en tu propia instancia, cifrados en reposo. Las funciones de IA usan una clave de proveedor que tú aportas o un modelo local, así que nada sale de tu instancia más allá del proveedor que configures, y no hay analítica de terceros sobre tus datos de salud."
}
}
+9
View File
@@ -7792,5 +7792,14 @@
"saved": "Donnée mise à jour.",
"discarded": "Document écarté."
}
},
"selfDescription": {
"intendedPurpose": "HealthLog est un outil personnel de suivi de santé et de bien-être. Il vous aide à enregistrer, visualiser et exporter vos propres données de santé. Il ne diagnostique, ne traite, ne guérit ni ne prévient aucune maladie, et n'est pas un dispositif médical.",
"coach": "Le Coach s'appuie sur vos propres données enregistrées. Ce n'est pas un médecin et il ne donne pas de conseil médical : pour un diagnostic ou un traitement, consultez un professionnel de santé.",
"insights": "Ce sont des tendances descriptives calculées à partir de vos propres données enregistrées, pas une évaluation clinique ni un diagnostic.",
"labs": "Ce sont vos propres relevés, pas un diagnostic médical. Les valeurs de référence varient selon le laboratoire et la personne : seul votre médecin peut les interpréter pour vous.",
"medications": "Ceci suit les médicaments que vous enregistrez et votre propre observance. Cela n'évalue ni les doses ni les interactions et n'est pas un conseil médical : confirmez-les avec votre pharmacien ou votre médecin.",
"emergency": "Si cela pourrait être une urgence, contactez maintenant votre numéro d'urgence local ou un professionnel de santé. HealthLog ne peut pas aider en cas d'urgence.",
"dataPosture": "HealthLog est auto-hébergé : vos données de santé restent sur votre propre instance, chiffrées au repos. Les fonctions d'IA utilisent une clé de fournisseur que vous apportez ou un modèle local, donc rien ne quitte votre instance au-delà du fournisseur que vous configurez, et il n'y a aucune analyse tierce de vos données de santé."
}
}
+9
View File
@@ -7792,5 +7792,14 @@
"saved": "Dato aggiornato.",
"discarded": "Documento scartato."
}
},
"selfDescription": {
"intendedPurpose": "HealthLog è uno strumento personale per la registrazione della salute e il benessere. Ti aiuta a registrare, visualizzare ed esportare i tuoi dati di salute. Non diagnostica, cura, guarisce né previene alcuna malattia e non è un dispositivo medico.",
"coach": "Il Coach lavora sui tuoi dati registrati. Non è un medico e non fornisce consigli medici: per una diagnosi o una terapia rivolgiti a un professionista sanitario.",
"insights": "Sono andamenti descrittivi calcolati dai tuoi dati registrati, non una valutazione clinica né una diagnosi.",
"labs": "Sono i tuoi referti, non una diagnosi medica. Gli intervalli di riferimento variano da laboratorio a persona: solo il tuo medico può interpretarli per te.",
"medications": "Questo registra i farmaci che annoti e la tua aderenza. Non valuta dosaggi o interazioni e non è un consiglio medico: confermali con il farmacista o il medico.",
"emergency": "Se potrebbe trattarsi di un'emergenza, contatta subito il numero di emergenza locale o un medico. HealthLog non può aiutare in caso di emergenza.",
"dataPosture": "HealthLog è self-hosted: i tuoi dati di salute restano sulla tua istanza, cifrati a riposo. Le funzioni di IA usano una chiave del provider che fornisci tu o un modello locale, quindi nulla lascia la tua istanza oltre il provider che configuri, e non c'è alcuna analisi di terze parti sui tuoi dati di salute."
}
}
+9
View File
@@ -7792,5 +7792,14 @@
"saved": "Dane zaktualizowane.",
"discarded": "Dokument odrzucony."
}
},
"selfDescription": {
"intendedPurpose": "HealthLog to osobiste narzędzie do rejestrowania zdrowia i dbania o dobre samopoczucie. Pomaga zapisywać, wizualizować i eksportować własne dane zdrowotne. Nie diagnozuje, nie leczy ani nie zapobiega żadnej chorobie i nie jest wyrobem medycznym.",
"coach": "Coach korzysta z Twoich własnych zapisanych danych. Nie jest lekarzem i nie udziela porad medycznych — po diagnozę lub leczenie zwróć się do pracownika ochrony zdrowia.",
"insights": "To opisowe wzorce wyliczone z Twoich własnych zapisanych danych, a nie ocena kliniczna ani diagnoza.",
"labs": "To Twoje własne zapisy, a nie diagnoza medyczna. Zakresy referencyjne różnią się w zależności od laboratorium i osoby — tylko Twój lekarz może je dla Ciebie zinterpretować.",
"medications": "To rejestruje leki, które zapisujesz, oraz Twoje stosowanie się do zaleceń. Nie ocenia dawkowania ani interakcji i nie jest poradą medyczną — potwierdź to u farmaceuty lub lekarza.",
"emergency": "Jeśli to może być nagły przypadek, zadzwoń teraz pod lokalny numer alarmowy lub skontaktuj się z lekarzem. HealthLog nie pomoże w nagłym przypadku.",
"dataPosture": "HealthLog jest hostowany samodzielnie: Twoje dane zdrowotne pozostają na Twojej instancji, zaszyfrowane w spoczynku. Funkcje AI korzystają z dostarczonego przez Ciebie klucza dostawcy lub modelu lokalnego, więc nic nie opuszcza Twojej instancji poza skonfigurowanym dostawcą i nie ma analityki firm trzecich na Twoich danych zdrowotnych."
}
}
+6
View File
@@ -6,6 +6,7 @@ import { useRouter } from "next/navigation";
import { useQueryClient } from "@tanstack/react-query";
import { Loader2, Pencil, Plus, ScanLine, Wrench } from "lucide-react";
import { MedicalDisclaimer } from "@/components/common/medical-disclaimer";
import { LabForm } from "@/components/labs/lab-form";
import { LabList } from "@/components/labs/lab-list";
import { OcrReviewDialog } from "@/components/labs/ocr-review-dialog";
@@ -173,6 +174,11 @@ export default function LabsPage() {
) : null}
<LabList onAddFirst={() => setDialogOpen(true)} />
{/* v1.25 — calm, context-specific framing for lab values: your own
records, ranges vary by lab and person, only a clinician interprets
them. One footer line, not a per-row banner. */}
<MedicalDisclaimer variant="labs" className="px-1 pt-2" />
</div>
);
}
+7
View File
@@ -7,6 +7,7 @@ import { useRouter, useSearchParams } from "next/navigation";
import { useAuth } from "@/hooks/use-auth";
import { useTranslations } from "@/lib/i18n/context";
import { queryKeys } from "@/lib/query-keys";
import { MedicalDisclaimer } from "@/components/common/medical-disclaimer";
import { MedicationWizardDialog } from "@/components/medications/wizard/medication-wizard-dialog";
import { MedicationCard } from "@/components/medications/medication-card";
import { Glp1MedicationCard } from "@/components/medications/glp1-medication-card";
@@ -524,6 +525,12 @@ export default function MedicationsPage() {
</div>
)}
{/* v1.25 — calm framing for the medications surface: this tracks what
you log and your own adherence, it doesn't assess dosing or
interactions and isn't medical advice. One footer line, neutral —
the med cards themselves stay un-tinted. */}
<MedicalDisclaimer variant="medications" className="px-1 pt-2" />
{/* v1.5.5 — the per-card kebab triggers used to open inline
IntakeImportDialog / ApiEndpointDialog mounts here, but both
state slots were only ever set from inside the dialogs
@@ -0,0 +1,75 @@
"use client";
import { cn } from "@/lib/utils";
import { useTranslations } from "@/lib/i18n/context";
/**
* v1.25 — the one place the app states what it is and is not.
*
* HealthLog's self-description standard is layered, not a wall of warnings:
* a single intended-purpose statement plus calm, context-specific notes that
* sit once on the surface they belong to. Every string is plain React text —
* no markdown renderer, in line with the project's XSS posture (Coach,
* briefing and insights all render as text children).
*
* The copy lives under the `selfDescription` i18n namespace so every locale
* carries the same set; pick the note that fits the surface:
*
* - `intendedPurpose` — the canonical "what this is / is not, not a medical
* device" line. Reuse verbatim; do not paraphrase per surface.
* - `coach` — the Coach standing line (works from your data, not a doctor).
* - `insights` — descriptive-patterns framing for insights + the briefing.
* - `labs` — your own records, ranges vary, only a clinician interprets.
* - `medications` — tracks what you log, not dosing/interaction advice.
* - `emergency` — the red-flag interstitial note (contact emergency services).
* - `dataPosture` — self-hosted, data stays on your instance, BYOK / local AI.
*
* The acknowledged onboarding disclaimer (`onboarding.disclaimer.*`) and the
* legal medical-device boundary on the public privacy page remain the standing
* floor; these notes are the gentle, in-context layer above it.
*/
export type DisclaimerVariant =
| "intendedPurpose"
| "coach"
| "insights"
| "labs"
| "medications"
| "emergency"
| "dataPosture";
const VARIANT_KEY: Record<DisclaimerVariant, string> = {
intendedPurpose: "selfDescription.intendedPurpose",
coach: "selfDescription.coach",
insights: "selfDescription.insights",
labs: "selfDescription.labs",
medications: "selfDescription.medications",
emergency: "selfDescription.emergency",
dataPosture: "selfDescription.dataPosture",
};
export interface MedicalDisclaimerProps {
variant: DisclaimerVariant;
className?: string;
}
/**
* A calm, muted, plain-text disclaimer line. Defaults to a small,
* unobtrusive footnote treatment; pass `className` to tune spacing for the
* surface. Keep it to one instance per surface — the standard is layered,
* not repeated.
*/
export function MedicalDisclaimer({
variant,
className,
}: MedicalDisclaimerProps) {
const { t } = useTranslations();
return (
<p
data-slot="medical-disclaimer"
data-variant={variant}
className={cn("text-muted-foreground text-xs leading-relaxed", className)}
>
{t(VARIANT_KEY[variant])}
</p>
);
}
@@ -2,6 +2,7 @@
import { Sparkles } from "lucide-react";
import { MedicalDisclaimer } from "@/components/common/medical-disclaimer";
import { cn } from "@/lib/utils";
import { useTranslations } from "@/lib/i18n/context";
@@ -121,6 +122,15 @@ export function CoachHero({ composer, scopeHint }: CoachHeroProps) {
{scopeHint}
</div>
) : null}
{/* v1.25 — the Coach standing self-description: works from your own
data, not a doctor, not medical advice. Sits once on the calm
new-chat surface so it frames the conversation without nagging
every reply. */}
<MedicalDisclaimer
variant="coach"
className="max-w-md text-center text-pretty"
/>
</div>
</div>
);
@@ -8,6 +8,7 @@ import { useMounted } from "@/hooks/use-mounted";
import { useFeatureFlags } from "@/hooks/use-feature-flags";
import { useWorkouts } from "@/hooks/use-workouts";
import { InsightsTabStrip } from "@/components/insights/insights-tab-strip";
import { MedicalDisclaimer } from "@/components/common/medical-disclaimer";
import {
nextAdvisorPollInterval,
useInsightsAdvisorQuery,
@@ -159,11 +160,14 @@ export function InsightsLayoutShell({ children }: { children: ReactNode }) {
modules={user?.modules}
/>
{children}
{/* v1.18.6 (DISC-01) — the page-level generic medical disclaimer is
removed. The "HealthLog is a private tracking tool, not a clinical
assessment or diagnosis" acknowledgment now lives once at the start
of onboarding, and the legal text stays reachable on the public
privacy page. */}
{/* v1.18.6 (DISC-01) — the page-level generic medical disclaimer was
removed; the standing acknowledgment lives once at the start of
onboarding and the legal text on the public privacy page.
v1.25 — one calm, context-specific framing line for the whole
Insights surface (the briefing, trends and correlations included):
these are descriptive patterns from the user's own data, not a
clinical assessment. Layered, not a wall of warnings. */}
<MedicalDisclaimer variant="insights" className="px-1" />
</div>
);
}
@@ -19,6 +19,7 @@ import { useQuery, useQueryClient } from "@tanstack/react-query";
import { Sparkles } from "lucide-react";
import { Badge } from "@/components/ui/badge";
import { MedicalDisclaimer } from "@/components/common/medical-disclaimer";
import { Label } from "@/components/ui/label";
import { NativeSelect } from "@/components/ui/native-select";
import { SettingsCard } from "@/components/settings/settings-card";
@@ -201,6 +202,11 @@ export function AiInsightsCard({
})
}
/>
{/* v1.25 — the data-posture statement lives where the provider key is
configured: self-hosted, data stays on this instance, BYOK / local
model, no third-party analytics. One calm line, not a banner. */}
<MedicalDisclaimer variant="dataPosture" />
</div>
</SettingsCard>
);
+28
View File
@@ -285,6 +285,19 @@ GROUND RULES
persuasion for its own sake. If a nudge would only serve to push, drop it
and reflect instead. You inform and support a decision that stays theirs;
you never manipulate it.
21. Describe HealthLog honestly when asked what you are, what this app is,
or where the user's data goes. HealthLog is a self-hosted personal
health record-keeping and wellness tool — it helps the user log,
visualise and export their OWN data. It is NOT a medical device and does
NOT diagnose, treat, cure or prevent any disease; you are an
informational assistant, not a doctor, and what you offer is not medical
advice. On data: the user's health data stays on their own instance,
encrypted at rest; AI runs on a provider key they bring or a local
model, so nothing leaves their instance beyond the provider they
configured, and there is no third-party analytics on their health data.
State this plainly and calmly when relevant; never oversell it as
confidential like a clinician's, and keep deferring diagnosis /
treatment / dose questions to a healthcare professional.
DAY-LEVEL READINGS — USE THE TIMELINE
@@ -844,6 +857,21 @@ GRUNDREGELN
selbst willen. Würde ein Anstoß nur dem Drängen dienen, lass ihn weg und
spiegele stattdessen. Du informierst und unterstützt eine Entscheidung, die
seine bleibt; du manipulierst sie nie.
21. Beschreibe HealthLog ehrlich, wenn der Nutzer fragt, was du bist, was
diese App ist oder wohin seine Daten gehen. HealthLog ist ein selbst
gehostetes, persönliches Werkzeug zur Gesundheitsdokumentation und zum
Wohlbefinden — es hilft dem Nutzer, seine EIGENEN Daten zu erfassen, zu
visualisieren und zu exportieren. Es ist KEIN Medizinprodukt und
diagnostiziert, behandelt, heilt oder verhindert KEINE Krankheit; du bist
ein informativer Begleiter, kein Arzt, und was du anbietest, ist keine
medizinische Beratung. Zu den Daten: Die Gesundheitsdaten des Nutzers
bleiben auf seiner eigenen Instanz, im Ruhezustand verschlüsselt; die KI
läuft über einen vom Nutzer mitgebrachten Anbieter-Schlüssel oder ein
lokales Modell, sodass nichts seine Instanz über den konfigurierten
Anbieter hinaus verlässt, und es gibt keine Drittanbieter-Analyse seiner
Gesundheitsdaten. Sag das klar und ruhig, wenn es passt; stell es nie als
vertraulich wie bei einer Ärztin dar und verweise Diagnose-, Behandlungs-
und Dosisfragen weiterhin an medizinisches Fachpersonal.
TAGES-LEVEL-MESSWERTE — NUTZE DIE TIMELINE