mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 04:32:42 +00:00
Add two cycle reminders through the existing notification cascade and the honest self-hosting privacy framing for reproductive-health data. Notifications: - New event types CYCLE_PERIOD_SOON (fires ~2 days before the predicted next-period start, from the cached prediction) and CYCLE_PERIOD_CONFIRM (a gentle "did your period start?" on/after the predicted start while no period is logged, within a short grace window). Both default OFF and are gated again on cycleTrackingEnabled — opt in twice for a sensitive surface. - A 15-minute pg-boss cron mirrors the mood-reminder worker: it scans users with cycle tracking enabled + predictionEnabled, computes who is in-window from the cached forecast, and dispatches one push per event per local day. Idempotency anchors on the push_attempts ledger (no new table). The queue is declared, registered in allQueues, scheduled, and wired to a boss.work handler, with a source-grep guard so it cannot ship unregistered. - Honours notificationPrefs.cycle.clientManaged (skip the server push when the device owns local reminders, with a suppressed annotation, mirroring the medication path) and CycleProfile.discreetNotifications (generic "HealthLog reminder" body so no cycle event is named on the lock screen). - Every attempt is recorded in push_attempts via the unchanged dispatcher. Privacy / disclaimer: - docs/self-hosting/reproductive-health-data.md — the "no cloud vendor to subpoena" framing with the honest residual-threat caveat (your own host, provider, backups, and devices remain part of the surface), citing the 2021 FTC settlement and 2025 verdict as public record only. - docs/security/cycle-data-threat-model.md — a compact "protects against / does not protect against" note, plus README pointers. - CyclePredictionDisclaimer component (reusing the GLP-1 estimate-disclaimer pattern) for every fertility/prediction surface: descriptive, not a contraceptive method, not medical advice, never a safe-to-have-unprotected -sex claim. 6-locale copy under cycle.disclaimer. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
53 lines
2.6 KiB
Markdown
53 lines
2.6 KiB
Markdown
# Cycle-data threat model
|
|
|
|
A compact statement of what self-hosting HealthLog's cycle tracking
|
|
protects against and what it does not. Pair this with the operator
|
|
guidance in
|
|
[`self-hosting/reproductive-health-data.md`](../self-hosting/reproductive-health-data.md).
|
|
|
|
The scope here is reproductive-health data specifically (menstrual,
|
|
fertility, pregnancy, contraception, sexual-activity fields), because
|
|
that is the category where the "who can reach my data" question carries
|
|
the highest stakes.
|
|
|
|
## What self-hosting + encryption-at-rest protects against
|
|
|
|
- **A cloud vendor holding your data.** There is no SaaS account and no
|
|
vendor key escrow. No third party can be served process for data it
|
|
does not have.
|
|
- **A stolen disk or a leaked backup, while the key is held separately.**
|
|
The intent-revealing fields are AES-256-GCM encrypted at rest; a disk
|
|
image without the `ENCRYPTION_KEYS` value does not yield them.
|
|
- **Casual lock-screen disclosure.** Discreet notifications collapse
|
|
every cycle reminder to a generic "HealthLog reminder" so the event is
|
|
never named on a lock screen.
|
|
- **Third-party analytics / ad-tech leakage.** HealthLog ships no
|
|
telemetry and no third-party trackers; cycle data is never sent to an
|
|
analytics or advertising endpoint.
|
|
|
|
## What it does NOT protect against
|
|
|
|
- **Seizure or compulsion of your own host.** If the running machine is
|
|
seized, imaged, or compelled, the data is on it. Encryption at rest
|
|
does not help against a live host or a key stored beside the data.
|
|
- **Your hosting provider.** A VPS provider can snapshot the disk and
|
|
can be served process. Self-hosting on rented infrastructure narrows
|
|
the set of parties that hold the data; it does not eliminate them.
|
|
- **Your own backups.** Any `pg_dump` or off-host export carries the
|
|
same data and must be protected as part of the same surface.
|
|
- **A compromised or unlocked client device.** A phone or laptop with a
|
|
live session or cached client holds data locally. Server-side
|
|
protection does nothing for an unlocked device.
|
|
- **Re-identification from "plaintext" fields.** Flow, basal body
|
|
temperature, ovulation tests, cervical mucus, and cycle dates stay in
|
|
plaintext so the engines can read them. They are health observations,
|
|
not the disclosure-sensitive intent fields — but they are still
|
|
health data on your host.
|
|
|
|
## The one-line version
|
|
|
|
Self-hosting means **no cloud vendor to subpoena**. It does **not** mean
|
|
the data is beyond reach: your own infrastructure, your provider, your
|
|
backups, and your devices are all still part of the surface. Size your
|
|
operator-side hardening to your own threat model.
|