From 92898b5271edb242962ef44e1ec3fc07e60d90b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Tue, 11 Aug 2026 17:36:15 +0200 Subject: [PATCH] docs(privacy): align the public data-flow disclosure --- src/app/privacy/__tests__/page.test.tsx | 81 +++- src/app/privacy/page.tsx | 530 +++++++++++++++++------- 2 files changed, 445 insertions(+), 166 deletions(-) diff --git a/src/app/privacy/__tests__/page.test.tsx b/src/app/privacy/__tests__/page.test.tsx index d145a5862..c08097add 100644 --- a/src/app/privacy/__tests__/page.test.tsx +++ b/src/app/privacy/__tests__/page.test.tsx @@ -31,8 +31,8 @@ function render() { return renderToStaticMarkup(); } -const POLICY_VERSION = "1.4.40"; -const LAST_UPDATED = "2026-05-18"; +const POLICY_VERSION = "1.37.11"; +const LAST_UPDATED = "2026-08-11"; describe("", () => { it("renders without crashing and includes the bilingual H1", () => { @@ -147,6 +147,7 @@ describe("", () => { const expectedProviders = [ "Anthropic", "OpenAI", + "Google LLC", "Withings", "Apple, Inc.", "Telegram", @@ -183,18 +184,19 @@ describe("", () => { // explicit guarantees (no raw HK identifiers, off by default, // encrypted in transit). expect(html).toContain("off by default"); - expect(html).toContain("never includes raw HealthKit identifiers"); + expect(html).toContain( + "raw HealthKit identifiers and raw sample IDs are not part", + ); expect(html).toContain("Anthropic"); expect(html).toContain("OpenAI"); }); - it("links the consent receipt endpoint with the retention window", () => { + it("links the consent receipt endpoint and states the actual lifecycle", () => { const html = render(); - // SB-3 requirement 4: consent receipt persistence — endpoint + - // retention period. - expect(html).toContain("GET /api/account/consents"); + expect(html).toContain("GET /api/consent/ai/latest"); expect(html).toContain("consent receipt"); - expect(html).toContain("five years"); + expect(html).toContain("cascade-deleted with the account"); + expect(html).not.toContain("receipts are retained for five years"); }); it("declares encryption in transit (TLS 1.3 + HSTS + cert pinning)", () => { @@ -218,24 +220,71 @@ describe("", () => { expect(html).toContain("operator"); }); - it("publishes the retention defaults (5y / 90d / 30d APNs)", () => { + it("publishes retention behavior supported by server jobs", () => { const html = render(); - // SB-3 requirement 7. - expect(html).toContain("5-year window"); - expect(html).toContain("Audit logs: 90 days"); - expect(html).toContain("Failed APNs deliveries: 30 days"); + expect(html).toContain("server default: 365 days"); + expect(html).toContain("after 90 days"); + expect(html).toContain("No global five-year deletion job"); + expect(html).toContain("active bucket lifecycle rule"); }); - it("discloses the GDPR Art. 17 deletion route + cascade behaviour", () => { + it("discloses the current deletion route, MFA handoff, and cascade", () => { const html = render(); - // SB-3 requirement 8: Settings → Daten → Konto löschen cascades - // through User.delete + onDelete: Cascade. + expect(html).toContain("Settings → Account → Delete account"); + expect(html).toContain("MFA-enrolled account"); + expect(html).toContain("authenticated web account page"); + expect(html).toContain("local account-bound data"); expect(html).toContain("Konto löschen"); expect(html).toContain("Delete account"); expect(html).toContain("User.delete"); expect(html).toContain("onDelete: Cascade"); }); + it("separates HealthLog storage from Apple-managed HealthKit sync", () => { + const html = render(); + expect(html).toContain("No HealthLog iCloud storage"); + expect(html).toContain("offline outbox"); + expect(html).toContain("medication-reminder scheduler database"); + expect(html).toContain("excluded from device backup"); + expect(html).toContain("Apple-managed behaviour"); + }); + + it("discloses every external AI topology and document operation", () => { + const html = render(); + expect(html).toContain("Server-managed:"); + expect(html).toContain("Bring your own key (BYO):"); + expect(html).toContain("On device:"); + expect(html).toContain("Google Gemini"); + expect(html).toContain("generic OpenAI-compatible destination"); + expect(html).toContain("stored original image or PDF"); + expect(html).toContain("Per-document chat"); + expect(html).toContain("Settings → Assistant"); + }); + + it("states the public heart-rate representation and excludes the experiment", () => { + const html = render(); + expect(html).toContain("supported default heart-rate representation"); + expect(html).toContain("raw-heart-rate experiment is unavailable"); + }); + + it("covers the linked App Store categories and declares no tracking", () => { + const html = render(); + for (const category of [ + "Health & Fitness", + "Sensitive Info", + "Name", + "Contact Info", + "User Content", + "Photos or Videos", + "Identifiers", + ]) { + expect(html).toContain(category); + } + expect(html).toContain("Tracking: No."); + expect(html).toContain("no advertising"); + expect(html).toContain("third-party analytics SDK"); + }); + it("publishes the operator email + GitHub fallback channel", () => { const html = render(); // SB-3 requirement 9: operator contact. The body uses the diff --git a/src/app/privacy/page.tsx b/src/app/privacy/page.tsx index 4d6095824..7fa8aeced 100644 --- a/src/app/privacy/page.tsx +++ b/src/app/privacy/page.tsx @@ -36,8 +36,8 @@ import Link from "next/link"; export const dynamic = "force-dynamic"; -const POLICY_VERSION = "1.4.40"; -const LAST_UPDATED = "2026-05-18"; +const POLICY_VERSION = "1.37.11"; +const LAST_UPDATED = "2026-08-11"; export const metadata: Metadata = { title: "Datenschutzerklärung / Privacy Policy — HealthLog", @@ -353,7 +353,7 @@ export default function PrivacyPage() {

HealthLog ist eine quelloffene, selbst-hostbare Anwendung zur persönlichen Gesundheitsprotokollierung. Der Quellcode wird - unter der GNU Affero General Public License v3.0 auf{" "} + unter der PolyForm Noncommercial License 1.0.0 auf{" "} github.com/MBombeck/HealthLog {" "} - under the GNU Affero General Public License v3.0. This policy + under the PolyForm Noncommercial License 1.0.0. This policy describes how the instance serving this page and the companion iOS application HealthLog for iOS (bundle identifier{" "} @@ -436,7 +436,10 @@ export default function PrivacyPage() { 2.1 Konto und Authentifizierung

    -
  • E-Mail-Adresse und gewählter Benutzername.
  • +
  • + Anzeigename und E-Mail-Adresse; optional ein vom Nutzer + ausgewähltes Profilbild. +
  • Passwort-Hash (Argon2id; das Klartext-Passwort wird zu keinem Zeitpunkt gespeichert oder protokolliert). @@ -481,18 +484,24 @@ export default function PrivacyPage() {

    Wenn der Nutzer der iOS-Anwendung Lesezugriff auf Apple HealthKit erteilt, liest HealthLog Stichproben der unten - aufgeführten Identifier. HealthKit-Daten verbleiben auf dem - Gerät des Nutzers und in dessen iCloud-gestütztem - Health-Speicher; die iOS-Anwendung überträgt die relevant- en - Stichproben über HTTPS (TLS 1.3, Zertifikat-Pinning) an den - HealthLog-Server (Endpunkt{" "} + aufgeführten Identifier. Apple Health verwaltet HealthKit-Daten + auf dem Gerät und kann sie nach den Apple-Einstellungen des + Nutzers über dessen Apple-Konto synchronisieren. Das ist + Apple-seitiges HealthKit-Verhalten und keine iCloud- oder + CloudKit-Speicherung durch HealthLog. Die iOS-Anwendung + überträgt relevante Stichproben über HTTPS (TLS 1.3, + Zertifikat-Pinning) an den HealthLog-Server (Endpunkt{" "} POST /api/measurements ), damit die Web-Oberfläche dieselben Verläufe darstellen kann - wie das iPhone. Es findet keine Übertragung an Dritte statt; die - Daten werden ausschließlich auf der unter Abschnitt 5 - beschriebenen Infrastruktur in Deutschland gespeichert. + wie das iPhone. HealthLog synchronisiert dabei die unterstützte + Standarddarstellung der Herzfrequenz für Trends und + Workout-Kontext. Das interne Experiment für einen ungefilterten + Roh-Herzfrequenzstrom ist in dieser öffentlichen Version nicht + verfügbar und wird nicht beworben oder erhoben. Eine Weitergabe + an einen KI-Anbieter erfolgt nur über die separat aktivierten + und eingewilligten Pfade in Abschnitt 2.7.

    HKQuantityTypeIdentifier:

    - 2.6 KI-Coach und Insights — Off-Device-Transit + 2.6 Dokumente, Scans und lokale Texterkennung

    - Aktiviert der Nutzer die KI-Coach-Oberfläche und konfiguriert - einen Sprachmodell-Anbieter, übermittelt HealthLog auf - Anforderung ein Snapshot-Bündel an diesen Anbieter. Das Bündel - enthält Gesundheitskontext aus den oben genannten Daten - (Aggregate, jüngste Beobachtungen, Zielbereiche, optionaler - Medikamentenkontext) und{" "} - - niemals rohe HealthKit-Identifier oder rohe Sample-IDs - - ; der Server normalisiert HK-Stichproben vorab in die interne - Metrik-Taxonomie. Die Übertragung erfolgt verschlüsselt (TLS - 1.3); standardmäßig ist die KI-Coach- Funktion deaktiviert und - wird nur nach ausdrücklicher Nutzereinwilligung pro Anbieter - aktiviert (siehe Einwilli- gungsnachweis unter Abschnitt 2.7). - HealthLog speichert keinen langlebigen Gesprächszustand über den - letzten Thread hinaus. Abschnitt 4 listet die in Frage kommenden - Anbieter (Anthropic, OpenAI) auf. + Ein Profilbild sowie für den Dokumententresor ausdrücklich + ausgewählte Fotos, Scans und PDFs werden zum HealthLog-Server + hochgeladen und dem Konto zugeordnet. Beim Schnell-Erfassen von + Medikamenten oder Laborwerten bleibt das Quellbild dagegen auf + dem Gerät: Apple Vision erkennt Text lokal, und nur die vom + Nutzer geprüften, bearbeiteten und bestätigten Zeilen werden an + den Server gesendet. Das gilt nicht automatisch als Upload in + den Dokumententresor.

    - 2.7 Einwilligungsnachweis (Consent Receipt) + 2.7 KI-Pfade, Ziele und Einwilligung

    - Jede Einwilligung in die KI-Übermittlung — sowohl die - Aktivierung pro Anbieter als auch Änderungen am - Datentiefe-Schalter — wird mit Zeitstempel, Anbieter, - Versionskennung des Einwilligungstextes und Hash des - Snapshot-Schemas als „Consent Receipt“ persistiert. - Der Endpunkt zum Abruf ist{" "} + Externe KI ist standardmäßig deaktiviert. Vor der ersten + Übertragung nennt die App das konkrete Ziel und die Kategorien: + die Frage oder Anweisung des Nutzers, Gesundheitskontext, + jüngste Beobachtungen oder Aggregate, Zielbereiche und optional + Medikamenten-, Labor- oder Dokumentkontext. Der Server + normalisiert HealthKit-Daten; rohe HealthKit-Identifier und rohe + Sample-IDs gehören nicht zum Coach-Snapshot. +

    +
      +
    • + Server-verwaltet: Die Daten gehen zuerst an + den konfigurierten HealthLog-Server und von dort an dessen + eingerichtetes Anthropic-, OpenAI-, lokales, ChatGPT-OAuth- + oder generisch OpenAI-kompatibles Ziel. Ein lokales oder + generisches Ziel wird vom Betreiber festgelegt und kann einer + eigenen Datenschutz- und Speicherrichtlinie unterliegen. +
    • +
    • + Eigener Schlüssel (BYO): Das iPhone sendet + direkt an OpenAI, Anthropic, Google Gemini oder einen vom + Nutzer angegebenen HTTPS-Endpunkt mit OpenAI-kompatibler API. + Der API-Schlüssel bleibt im iOS-Keychain und wird nicht an den + HealthLog-Server gesendet. +
    • +
    • + Auf dem Gerät: Apple Foundation Models und + die lokale Texterkennung senden Bild, Prompt und Ergebnis an + keinen Drittanbieter in der Cloud. Ein ausdrücklich gewählter + Netzwerk-Endpunkt ist dagegen kein reiner On-Device-Pfad und + wird vor Verwendung als Ziel angezeigt. +
    • +
    +

    + Bei Dokumenten können Vorschlag, Zusammenfassung und Index nach + Einwilligung das gespeicherte Originalbild bzw. PDF oder den + erkannten Text verarbeiten. Der Dokument-Chat sendet die Frage + des Nutzers zusammen mit dem indexierten Kontext des gewählten + Dokuments und streamt eine darauf gestützte Antwort zurück. Die + Freigabe gilt nicht für andere Ziele. Unter{" "} + Einstellungen → Assistent kann der Nutzer externe KI + ausschalten oder den Anbieter wechseln; damit werden weitere + Server-Anfragen blockiert. Beim BYO-Pfad entfernt der Widerruf + zusätzlich Schlüssel und Freigabe für diesen Anbieter. +

    +

    + 2.8 Einwilligungsnachweis (Consent Receipt) +

    +

    + Der Server hält für server-verwaltete KI einen kontogebundenen + Einwilligungsnachweis mit Art, signiertem Zeitpunkt und + Artefakt. Der aktuelle Status ist über{" "} - GET /api/account/consents - - ; die Speicherdauer der Belege beträgt fünf Jahre, danach werden - sie automatisch gelöscht. Ein Widerruf wird als eigenes Receipt - mit umgekehrter Polarität abgelegt; der Anbieter erhält ab - diesem Zeitpunkt keine Snapshot-Bündel mehr. + GET /api/consent/ai/latest + {" "} + abrufbar. Ein Widerruf wird mit Zeitstempel festgehalten und + blockiert zukünftige externe Verarbeitung. Diese Nachweise + werden als Teil des Konto-Auditverlaufs aufbewahrt und bei der + Konto-Löschung kaskadiert gelöscht; es gibt keinen belegten + separaten festen Fünf-Jahres-Löschjob.

    - 2.8 Geräte- und Integrations-Metadaten, Push + 2.9 Geräte- und Integrations-Metadaten, Push

    • @@ -684,26 +730,32 @@ export default function PrivacyPage() {

    - 2.9 Sicherheits- und Audit-Logs + 2.10 Sicherheits- und Audit-Logs

    • - Authentifizierungs-Ereignisse (Login-Erfolg/-Fehlschlag, - Passkey-Registrierung, Passwort-Wechsel, Sitzungs- Widerruf) — - 90 Tage zur forensischen Aufklärung. + Authentifizierungs- und Konto-Ereignisse für Sicherheit, + Missbrauchsschutz und Nachvollziehbarkeit. Die Instanz löscht + Audit-Zeilen täglich nach ihrem konfigurierten Fenster; der + Server-Standard beträgt 365 Tage und kann vom Betreiber + geändert werden.
    • - Server-Zugriffsprotokolle (Zeit, Pfad, Statuscode, User- - Agent, IP) — 14 Tage zur Missbrauchsbekämpfung und - Fehlersuche. + Server- und Reverse-Proxy-Zugriffsprotokolle werden nur für + Betrieb, Missbrauchsschutz und Fehlersuche benötigt und nach + der aktiven Log-Rotation des Betreibers gelöscht. Diese + Codebasis belegt kein festes 14-Tage-Fenster für die + Produktions-Infrastruktur.
    • - Fehlgeschlagene APNs-Zustellungen — 30 Tage zur Wartung des - Push-Pfads, danach automatische Löschung. + Push-Zustellversuche aller aktivierten Kanäle enthalten Kanal, + Ereignistyp, Ergebnis und Fehlerklasse, aber keinen + Roh-Gesundheitswert. Ein täglicher Job löscht sie nach 90 + Tagen.

    - 2.10 Nicht erhobene Daten + 2.11 Nicht erhobene Daten

    • @@ -738,7 +790,10 @@ export default function PrivacyPage() { 2.1 Account and authentication
        -
      • Email address and chosen username.
      • +
      • + Display name and email address; optionally, a profile image + selected by the user. +
      • Password hash (Argon2id; the plain-text password is never stored or logged). @@ -783,16 +838,22 @@ export default function PrivacyPage() {

        When the user grants the iOS application read access to Apple HealthKit, HealthLog reads samples for the identifiers listed - below. HealthKit data remains on the user's device and the - user's iCloud-backed Health store; the iOS application + below. Apple Health manages HealthKit data on the device and may + sync it through the user's Apple account according to Apple + platform settings. That is Apple-managed HealthKit behaviour, + not iCloud or CloudKit storage by HealthLog. The iOS application copies relevant samples to the HealthLog server over HTTPS (TLS 1.3, certificate pinning) via{" "} POST /api/measurements {" "} - so the web surface can render the same trends as the iPhone. No - third-party transit; data lives on the German-located - infrastructure described in section 5. + so the web surface can render the same trends as the iPhone. + HealthLog syncs the supported default heart-rate representation + used for trends and workout context. The internal unfiltered + raw-heart-rate experiment is unavailable in this public build; + it is neither advertised nor collected. Transit to an AI + provider occurs only through the separately enabled and + consented paths in section 2.7.

        HKQuantityTypeIdentifier:

        - 2.6 AI Coach and Insights — off-device transit + 2.6 Documents, scans, and local text recognition

        - When the user enables the AI Coach surface and configures a - language-model provider, HealthLog sends a snapshot bundle to - that provider on demand. The bundle contains health context - derived from the data above (aggregates, recent observations, - target ranges, optional medication context) and{" "} - - never includes raw HealthKit identifiers or raw sample IDs - - ; the server normalises HK samples into the internal metric - taxonomy first. Transit is encrypted (TLS 1.3). The AI Coach is - off by default and is enabled per- provider only after explicit - user consent (see consent receipt in section 2.7). HealthLog - does not retain long-term conversation state beyond the most - recent thread. Section 4 enumerates the eligible providers - (Anthropic, OpenAI). + A profile image and photos, scans, or PDFs explicitly selected + for the document vault are uploaded to the HealthLog server and + linked to the account. Medication and lab quick-entry work + differently: Apple Vision recognises text on the device, the + source image is not uploaded, and only rows the user reviews, + edits, and confirms are sent to the server. Quick entry does not + automatically save the source image in the document vault.

        - 2.7 Consent receipt persistence + 2.7 AI paths, destinations, and consent

        - Every consent to AI transit — both per-provider activation and - changes to the data-depth toggle — is persisted as a - “consent receipt” with timestamp, provider, - consent-text version, and a hash of the snapshot schema. The - retrieval endpoint is{" "} + External AI is off by default. Before the first transmission, + the app identifies the destination and categories: the + user's question or instruction, health context, recent + observations or aggregates, target ranges, and optional + medication, lab, or document context. The server normalises + HealthKit data; raw HealthKit identifiers and raw sample IDs are + not part of a Coach snapshot. +

        +
          +
        • + Server-managed: data first reaches the + configured HealthLog server and is then sent to that + server's configured Anthropic, OpenAI, local, ChatGPT + OAuth, or generic OpenAI-compatible destination. A local or + generic destination is chosen by the operator and may have its + own privacy and retention policy. +
        • +
        • + Bring your own key (BYO): the iPhone sends + directly to OpenAI, Anthropic, Google Gemini, or a + user-specified HTTPS OpenAI-compatible endpoint. The API key + remains in the iOS Keychain and is not sent to the HealthLog + server. +
        • +
        • + On device: Apple Foundation Models and local + text recognition do not send the image, prompt, or result to a + third-party cloud provider. An explicitly selected network + endpoint is not an on-device path and is identified before + use. +
        • +
        +

        + For documents, suggest, summary, and index operations may + process the stored original image or PDF, or recognised text, + after consent. Per-document chat sends the user's question + with indexed context from the selected document and streams a + grounded answer back. Consent does not transfer to a different + destination. The user can disable external AI or change the + provider under Settings → Assistant; this blocks future + server requests. For BYO, revocation also removes that + provider's key and grant. +

        +

        + 2.8 Consent receipt persistence +

        +

        + For server-managed AI, the server keeps an account-bound consent + receipt with its kind, signed time, and artefact. The current + state is available through{" "} - GET /api/account/consents + GET /api/consent/ai/latest - ; receipts are retained for five years and then deleted - automatically. A withdrawal is recorded as a separate - reverse-polarity receipt; from that moment the provider receives - no further snapshot bundles. + . Withdrawal is timestamped and blocks future external + processing. Receipts remain part of the account audit trail and + are cascade-deleted with the account; no separate fixed + five-year cleanup job is evidenced by the server source.

        - 2.8 Device and integration metadata, push + 2.9 Device and integration metadata, push

        • @@ -978,26 +1076,30 @@ export default function PrivacyPage() {

        - 2.9 Security and audit + 2.10 Security and audit

        • - Authentication events (login success / failure, passkey - registration, password change, session revocation) — retained - for 90 days for security forensics. + Authentication and account events used for security, abuse + prevention, and accountability. The instance removes audit + rows daily according to its configured window; the server + default is 365 days and the operator may change it.
        • - Server access logs (timestamp, request path, status code, - user-agent, IP address) — 14 days for abuse- rate-limiting and - debugging. + Server and reverse-proxy access logs are needed only for + operations, abuse prevention, and debugging, and are removed + under the operator's active log-rotation policy. This + source tree does not evidence a fixed 14-day production + window.
        • - Failed APNs deliveries — 30 days to support push- pipeline - maintenance, then auto-deleted. + Push-delivery attempts for every enabled channel store the + channel, event type, result, and error class, but no raw + health value. A daily job removes them after 90 days.

        - 2.10 Data we do not collect + 2.11 Data we do not collect

        • @@ -1126,13 +1228,14 @@ export default function PrivacyPage() { bodyDe={ <>

          - Folgende Anbieter können personenbezogene Daten im Auftrag des - Betreibers verarbeiten. Die Liste ist für den veröffentlichten - Funktionsumfang abschließend. Anbieter werden nur für die - Funktionen eingebunden, die der Nutzer ausdrücklich aktiviert - hat. Für jede Übertragung in Drittländer (insbesondere USA) - bestehen Standardvertrags- klauseln nach Art. 46 Abs. 2 lit. c - DSGVO mit dem jeweiligen Anbieter. + Folgende benannte Anbieter können personenbezogene Daten für + aktivierte Funktionen verarbeiten. Zusätzlich kann ein Betreiber + oder BYO-Nutzer einen lokalen oder generischen HTTPS-Endpunkt + mit OpenAI-kompatibler API festlegen. Für ein solches nutzer- + oder betreiberdefiniertes Ziel gelten dessen eigene Angaben zu + Verantwortlichkeit, Ort und Speicherdauer; deshalb ist die Liste + nicht als abschließend für frei konfigurierbare Ziele zu + verstehen.

          Die englische Übersetzung enthält die detaillierte Auflistung @@ -1144,13 +1247,12 @@ export default function PrivacyPage() { bodyEn={ <>

          - The following providers may process personal data on behalf of - the HealthLog operator. The list is exhaustive for the released - feature set; sub-processors are only engaged for the features - the user has explicitly enabled. Each transfer to a third - country (notably the United States) is covered by Standard - Contractual Clauses under Art. 46 (2) (c) GDPR with the - respective provider. + The named providers below may process personal data for enabled + features. An operator or BYO user may also configure a local or + generic HTTPS endpoint with an OpenAI-compatible API. That user- + or operator-specified destination is governed by its own + controller, location, and retention terms, so this list is not + exhaustive for freely configurable destinations.

            +
          • Backups — - täglich, verschlüsselt, 30 Tage Aufbewahrung auf einem - S3-kompatiblen Objektspeicher mit eigener - Verschlüsselungsschicht. + sofern der Betreiber die optionale Off-Host-Sicherung aktiviert, + werden tägliche Konto-Exporte mit einem separaten + AES-256-GCM-Schlüssel in einen S3-kompatiblen Objektspeicher + geschrieben. Die Aufbewahrung wird vom Betreiber und der + kanonischen Bucket-Lifecycle-Regel festgelegt; die Codebasis + kann die aktuell eingesetzte Produktionsregel nicht belegen.
          • - Standard-Speicherdauern + Gesundheitsdaten {" "} - — Messungen: gleitendes 5-Jahres-Fenster (Roh-Stichproben älter - als 5 Jahre werden automatisch verdichtet bzw. gelöscht; - aggregierte Verläufe bleiben). Audit-Logs: 90 Tage. - Server-Zugriffsprotokolle: 14 Tage. Fehl- geschlagene - APNs-Zustellungen: 30 Tage. Einwilligungs- belege: 5 Jahre. + — kontobezogene Messungen bleiben bis zur Nutzerlöschung oder + Konto-Löschung erhalten, soweit kein typbezogener + Verdichtungsjob greift. Rohe dichte Herzfrequenz-, HRV- und + Sauerstoffsättigungs-Stichproben werden nach 90 Tagen zu + stündlichen Mittelwerten verdichtet; Tages-Rollups bewahren + Mittelwert und Extremwerte. Es gibt keinen belegten globalen + Fünf-Jahres-Löschjob für alle Messungen. +
          • +
          • + + Betriebs- und Einwilligungsdaten + {" "} + — Audit-Logs werden täglich nach dem konfigurierten Fenster + gelöscht (Server-Standard: 365 Tage). Push-Zustellversuche + werden täglich nach 90 Tagen gelöscht. Server- und + Reverse-Proxy-Logs folgen der aktiven Log-Rotation des + Betreibers. Einwilligungsnachweise bleiben im Konto-Auditverlauf + bis zur Konto-Löschung. Für externe KI-Anfragen gilt die + Richtlinie des vor der Übertragung genannten Anbieters oder + Endpunktbetreibers. +
          • +
          • + + Kein HealthLog-iCloud-Speicher + {" "} + — HealthLog speichert Server-Datenbank, lokale Gesundheits- + caches, Offline-Outbox, ECG- und Workout-Payloads, + KI-Transkript-Cache, Medikamentenplaner-Datenbank sowie Widget- + und Watch-Snapshots weder in iCloud noch in CloudKit. Lokale + gesundheitsbezogene Speicher liegen in geschütztem App- oder + App-Group-Speicher, deaktivieren CloudKit soweit anwendbar und + sind ausdrücklich vom Geräte-Backup ausgeschlossen. Eine + mögliche Apple-Health-Synchronisation ist davon getrennt und + wird allein von Apple verwaltet.
          • Löschung — der Endpunkt zur Konto-Löschung läuft kaskadiert durch jede nutzer-skopierte Tabelle: Gesundheitsmessungen, Sitzungen, Audit-Log, Integrations-Token, Push- Abonnements, Erfolge, - hochgeladene Dateien. Die Löschung erfolgt sofort; Backups - laufen innerhalb des 30-Tage- Fensters aus. + hochgeladene Dateien. Die Löschung erfolgt sofort im aktiven + Serverbestand; neue Backups enthalten das Konto danach nicht + mehr, ältere Sicherungskopien laufen nach der aktiven + Bucket-Lifecycle-Regel des Betreibers aus.
          } @@ -1324,24 +1470,55 @@ export default function PrivacyPage() {
        • Backups — - daily, encrypted, retained for 30 days on an S3- compatible - object store with its own encryption-at- rest layer. + when the operator enables optional off-host backup, daily + account exports are encrypted under a separate AES-256-GCM key + and written to an S3-compatible object store. Retention is set + by the operator and the canonical bucket lifecycle rule; the + source tree cannot prove the currently deployed production rule. +
        • +
        • + Health data{" "} + — account-linked measurements remain until the user deletes them + or the account, unless a type-specific consolidation job + applies. Raw dense heart-rate, HRV, and oxygen-saturation + samples consolidate into hourly means after 90 days; daily + rollups preserve the mean and extremes. No global five-year + deletion job for all measurements is evidenced by the server.
        • - Default retention windows + Operational and consent data {" "} - — measurements: rolling 5-year window (raw samples older than 5 - years are aggregated or removed; long-arc aggregates persist). - Audit logs: 90 days. Server access logs: 14 days. Failed APNs - deliveries: 30 days. Consent receipts: 5 years. + — audit logs are pruned daily under the configured window + (server default: 365 days). Push-delivery attempts are pruned + daily after 90 days. Server and reverse-proxy logs follow the + operator's active log rotation. Consent receipts remain in + the account audit trail until account deletion. External-AI + requests follow the policy of the provider or endpoint operator + identified before transmission. +
        • +
        • + + No HealthLog iCloud storage + {" "} + — HealthLog does not store its server database, local health + caches, offline outbox, ECG or workout payloads, AI transcript + cache, medication-reminder scheduler database, or widget and + Watch health snapshots in iCloud or CloudKit. Local + health-bearing stores use protected app or application-group + storage, disable CloudKit where applicable, and are explicitly + excluded from device backup. Apple Health may separately sync + HealthKit data under Apple's platform controls; that is + Apple-managed behaviour, not HealthLog cloud storage.
        • Deletion — the account-deletion endpoint cascades through every user-scoped table: health observations, sessions, audit log, integration tokens, push subscriptions, achievements, uploaded files. - Deletion is immediate; backups age out under the 30-day window. + Deletion is immediate in the active server store. New backups + then omit the account; older backup copies age out under the + operator's active bucket lifecycle rule.
        } @@ -1373,8 +1550,14 @@ export default function PrivacyPage() { Recht auf Löschung (Art. 17) {" "} - — Einstellungen → Daten → Konto löschen. Die Aktion - kaskadiert sofort über alle nutzer-skopierten Tabellen via{" "} + — Einstellungen → Konto → Konto löschen. Nach + erfolgreicher Server-Löschung entfernt die App sofort alle + kontogebundenen lokalen Daten. Bei einem Konto mit MFA kann die + App zur authentifizierten Web-Kontoseite weiterleiten, damit der + Nutzer den erforderlichen frischen Identitätsnachweis erbringt; + nach Rückkehr erkennt die App die bestätigte Löschung und führt + dieselbe lokale Bereinigung aus. Die Server-Aktion kaskadiert + über alle nutzer-skopierten Tabellen via{" "} User.delete {" "} @@ -1382,7 +1565,8 @@ export default function PrivacyPage() { onDelete: Cascade - ; Backups laufen innerhalb des 30-Tage-Fensters aus. + . Neue Sicherungen enthalten das gelöschte Konto nicht; ältere + Kopien laufen nach der aktiven Bucket-Lifecycle-Regel aus.
      • @@ -1439,8 +1623,13 @@ export default function PrivacyPage() { Right to erasure (Art. 17) {" "} - — Settings → Data → Delete account. The action cascades - immediately through every user-scoped table via{" "} + — Settings → Account → Delete account. After successful + server deletion, the app immediately removes all local + account-bound data. For an MFA-enrolled account, the app may + hand off to the authenticated web account page for the required + fresh identity check; on return it detects confirmed deletion + and performs the same local cleanup. The server action cascades + through every user-scoped table via{" "} User.delete {" "} @@ -1448,7 +1637,8 @@ export default function PrivacyPage() { onDelete: Cascade - ; backups age out within the 30-day window. + . New backups omit the deleted account; older copies age out + under the active bucket lifecycle rule.
      • @@ -1555,8 +1745,8 @@ export default function PrivacyPage() {

        Die Privacy-Nutrition-Labels der iOS-Anwendung in App Store Connect ordnen sich folgenden Kategorien zu (jeweils{" "} - linked to the user, ausschließlich zur App- Funktion - verwendet): + linked to the user, zur App-Funktion und, soweit + angegeben, Konto-Verwaltung):

        • @@ -1571,6 +1761,11 @@ export default function PrivacyPage() { {" "} (Blutdruck, Blutzucker, Medikamente).
        • +
        • + Name — + Anzeigename für Profil und Berichte; App-Funktion und + Konto-Verwaltung. +
        • Kontakt-Informationen @@ -1581,7 +1776,16 @@ export default function PrivacyPage() { Nutzer-Inhalte {" "} - (Notizen zu Messungen, Stimmungsnotizen). + (Notizen, Prompts und Fragen, geprüfter OCR- und + Dokumenttext). +
        • +
        • + + Fotos oder Videos + {" "} + (Profilbild sowie ausdrücklich hochgeladene + Dokumentfotos/-scans; Schnell-Erfassungsbilder bleiben auf dem + Gerät).
        • Kennungen{" "} @@ -1599,6 +1803,13 @@ export default function PrivacyPage() { angehängten GPS-Workout-Route.
        +

        + Tracking: Nein. HealthLog verwendet keine + Werbung, kein anwendungsübergreifendes Tracking, keine + Werbemessung und kein Drittanbieter-Analytics-SDK. Optionale + KI-Anbieter erhalten Daten nur für die vom Nutzer ausgelöste + App-Funktion, nicht für Werbung oder Tracking. +

        } bodyEn={ @@ -1606,7 +1817,8 @@ export default function PrivacyPage() {

        The iOS application's Privacy Nutrition Labels in App Store Connect map to the following categories (each - linked to the user, used only for app functionality): + linked to the user, used for app functionality and, + where stated, account management):

        • @@ -1621,6 +1833,11 @@ export default function PrivacyPage() { {" "} (blood pressure, glucose, medications).
        • +
        • + Name — + display name for the profile and reports; app functionality + and account management. +
        • Contact Info @@ -1631,9 +1848,16 @@ export default function PrivacyPage() { User Content {" "} - (notes attached to measurements, mood notes, bug- report + (notes, prompts and questions, reviewed OCR and document text).
        • +
        • + + Photos or Videos + {" "} + (profile image and explicitly uploaded document photos or + scans; quick-entry images stay on the device). +
        • Identifiers @@ -1653,6 +1877,12 @@ export default function PrivacyPage() { attaches manually to a workout.
        +

        + Tracking: No. HealthLog uses no advertising, + cross-app tracking, advertising measurement, or third-party + analytics SDK. Optional AI providers receive data only for the + app function the user invokes, not for advertising or tracking. +

        } />