131 Commits
Author SHA1 Message Date
Marc-André Bombeck db391aa4ce chore(release): v1.15.5 — insights layout, navigation, password-reset CLI 2026-06-06 21:32:16 +02:00
Marc-André Bombeck 6bc2294f59 chore(release): v1.15.4 — cycle and insights polish 2026-06-06 20:49:16 +02:00
Marc-André Bombeck 6dc241ccb1 chore(release): v1.15.3 — cycle summary on the insights page 2026-06-06 19:44:53 +02:00
Marc-André Bombeck d601c6c860 chore(release): v1.15.2 — cycle insights crash fix 2026-06-06 19:16:05 +02:00
Marc-André Bombeck b4ab3ad10c chore(release): v1.15.1 — cycle premium parity, reminder polish, fixes 2026-06-06 17:23:22 +02:00
Marc-André BombeckandClaude Opus 4.8 6745850f16 chore(release): v1.15.0 — cycle tracking
Cut v1.15.0: the private menstrual-cycle vertical. Quick-entry day-log
(period/flow, BBT, mucus, OPK + pregnancy/progesterone tests,
contraception, intercourse, graded symptoms), a calendar + signature
cycle wheel, honest range predictions with confidence + a read-your-body
mode, a BBT chart, phase×vitals + symptom-by-phase insights, opt-in
per-channel reminders, encryption of intent fields, discreet
notifications, a one-tap data purge, and Apple-Health reproductive import
+ health-record export. Predictions run on a deterministic engine the iOS
client mirrors offline.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 13:52:21 +02:00
Marc-André BombeckandClaude Opus 4.8 eec3557137 feat(cycle): symptom-by-phase patterns on the insights tab
Add the cycle-native counterpart to the phase×vitals crosstab: for each
logged symptom, where in the cycle it clusters. A pure aggregator tallies
each symptom's occurrences across the phase-labelled days (the same phase
map the calendar uses), surfaces only symptoms logged on at least three
phased days, and reports per-phase counts + the dominant phase + its
share. The insights tab renders it as a proportional phase-hued bar with
the dominant phase named in words (never colour-only), observational and
never causal.

Also correct the phase-crosstab OpenAPI row enum, which had drifted
behind the runtime (mood + glucose channels were missing).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 13:47:04 +02:00
Marc-André BombeckandClaude Opus 4.8 c21131e26e feat(cycle): second-audit feature, QoL, and wiring close
Close the second-round audit UI cluster:

- Cycle reminders: add the missing notification-event labels so the
  period-soon / period-confirm toggles read correctly on the
  notifications page, and point to them from cycle settings.
- Per-cycle history: render a recent-cycles list (range, length, period
  length, confirmed-ovulation chip) — the cycles were fetched but only
  the aggregate stats showed.
- Confirmed ovulation: carry it on the prediction DTO and surface it as a
  solid BBT-chart marker + a predictions row + a history chip.
- Log-day sheet: deselecting an enum now clears it (edits route through
  the nullable PATCH); period start/end work on any selected date for
  retroactive correction; "end period" shows only while one is open.
  Extract the payload builders as pure, unit-tested functions.
- Cycle-tracking enable toggle in account settings so any account can opt
  in before the gated page is reachable; wire the cycle data-purge button
  to the hard-delete route and document the route in the OpenAPI spec.
- Calendar legend: add the symptom dot, render fertile as a ring to match
  the grid; tighten the luteal prior bound to the engine clamp; mute the
  BBT ovulation-label colour for contrast.
- Share the cycle-start backward-walk between the wheel and the chart.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 13:32:25 +02:00
Marc-André BombeckandClaude Opus 4.8 31a14ce7bf feat(cycle): premium cycle ring, BBT chart, and full read-state coverage
Finish the cycle web vertical's signature surfaces:

- Rebuild the cycle wheel to the wellness-ring premium signature — a
  clockwise clock-wipe that draws the phase arcs on from the 12-o'clock
  day-0 origin, a phase-tinted bloom on the active arc, the shared
  specular sheen, a day-number count-up, and a soft current-day marker
  halo. All on the wellness-tile surface, gated once per session and
  zeroed under prefers-reduced-motion.
- Add the basal-body-temperature chart to the predictions tab: the
  current-cycle BBT series with phase-tinted points, fertility signs in
  the tooltip, and an estimated-ovulation reference line (suppressed in
  raw-chart mode). Surface basalBodyTempC + ovulation-test + mucus on the
  calendar day DTO so the chart reads from the existing calendar load.
- Cover the read states the prediction/disclaimer surfaces were missing:
  pass the disclaimer to the predictions panel, render it on the calendar
  tab, add per-tab error + retry, and gate the settings spinner.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 13:09:00 +02:00
Marc-André BombeckandClaude Opus 4.8 4b10bdc5da feat(cycle): single-day read endpoint, symptom severity, and a richer log-day sheet
Add `GET /api/cycle/day-logs?date=YYYY-MM-DD` returning the full day-log DTO
(or null) for one tz-anchored day so the web log-day sheet pre-fills instead
of opening blank — a blank re-log no longer nulls untouched or HealthKit-sourced
fields. Delete resolves the row id from the same read.

Persist an optional 1-4 Likert severity per symptom link (migration
0133_v1150_cycle_symptom_severity), carried through the shared symptom-link
writer and surfaced in the day-log DTO.

Sheet now captures the previously missing fields — spotting between periods,
pregnancy/progesterone home-test results, contraceptive kind — plus per-symptom
severity chips, a one-tap end-period boundary, and a Delete action. The wheel
ring marker sits at the 12-o'clock origin again (drop the double rotation), the
cycle view goes two-column on desktop, and the empty ring carries a first-period
call to action. New copy is localized across all six locales; the prediction and
fertility surfaces keep their disclaimers.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 12:39:28 +02:00
Marc-André BombeckandClaude Opus 4.8 15bece9849 fix(cycle): scope symptothermal to the current cycle, unify luteal clamp, widen fertile + crosstab coverage
The symptothermal layer ran against the full day-log history: detectTempShift
returned the earliest 3-over-6 rise and detectMucusPeak the last egg-white day
across all cycles, so a multi-cycle user with historical BBT confirmed a
months-old ovulation and the predicted next-period start landed in the past.
Scope the temperature/mucus detectors to the current cycle window
[lastConfirmedStart − BBT_WINDOW, today], take the latest qualifying temp shift,
and reject any confirmation whose next-start is already in the past.

Resolve luteal length through a single clamp. The predictor clamped to [10,16]
while the calendar adapter and phase mapper used the raw stored value, so the
ovulation dot and the OVULATORY band could land on different days for an
out-of-clamp profile. Export resolveLuteal/clampLuteal, route buildCalendar,
buildPhaseCycles and phaseForDay through it, and tighten the profile-prefs Zod
bound to the same [10,16] range.

Show the fertile window for AVOID_PREGNANCY as well as TRYING_TO_CONCEIVE per the
algorithm spec; it stays hidden for GENERAL_HEALTH/PERIMENOPAUSE.

Bound the day-log reads on the calendar and insights routes to the rendered span
plus the symptothermal lookback instead of the full history; cycle-length stats
already run off the MenstrualCycle rows.

Add mood and blood glucose as phase-crosstab outcome metrics under the same FDR
and per-group day floors. Mood is read from MoodEntry and injected as a synthetic
channel since it is not a measurement row.

Add multi-cycle, luteal-clamp and fertile-window fixtures.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 12:06:48 +02:00
Marc-André BombeckandClaude Opus 4.8 e984ada5f1 feat(cycle): import Apple Health reproductive data into cycle, add cycle export
Promote the reproductive HealthKit category types out of the
Apple-Health-import privacy-hold list and route them into cycle day-logs
instead of measurements, and surface cycle data on the three export
surfaces.

Import promotion:
- A new HealthKit -> cycle mapping module is the single source of truth for
  how MenstrualFlow, IntermenstrualBleeding, CervicalMucusQuality,
  OvulationTestResult, SexualActivity, PregnancyTestResult,
  ProgesteroneTestResult, Contraceptive and the symptom category types fold
  into CycleDayLog fields / seeded symptom keys. The XML importer
  accumulates same-day reproductive samples and writes one canonical
  day-log per day with source APPLE_HEALTH and a synthetic per-day
  externalId for idempotent re-import. The fold is gated on cycle tracking
  being enabled, so a non-cycle export never provisions cycle rows. A
  contraceptive method nudges the profile goal toward avoiding pregnancy
  only when the goal is still on its default. Basal body temperature stays
  a measurement and mirrors onto the day-log. Pregnancy/Lactation status
  and the pregnancy-bleeding types stay deferred; the cycle awareness types
  remain server-derived.

Export:
- FHIR emits LMP (LOINC 8665-2), average cycle length (64700-8), period
  length (64698-4) and the current phase as opt-in reproductive-health
  observations grouped into their own document section.
- The doctor PDF gains an opt-in cycle section (recent cycles, average
  length and variability, current phase), privacy-default off like mood.
- The full-backup export, the weekly backup worker and the off-host DR
  snapshot include the cycle tables, and the admin restore re-creates them;
  the day-log note round-trips as ciphertext and is never decrypted onto a
  report surface.

Mapping table documented in docs/api/cycle-healthkit-mapping.md. Adds unit
+ integration coverage for the mapping, the import routing, the FHIR
observations and the backup round-trip. OpenAPI regenerated. Six-locale
strings added.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 10:16:54 +02:00
Marc-André BombeckandClaude Opus 4.8 77a652a47c feat(cycle): cycle-phase correlation insight + Coach phase dimension
Add the menstrual-cycle phase as a channel in the existing FDR-guarded
correlation machinery, the same way rated mood factors were folded in —
no new statistics, the same Welch + Benjamini-Hochberg pipeline, the same
day floors and q = 0.10 gate.

Two complementary mechanisms, both confined to a gender-gated surface:
- a categorical luteal-vs-follicular contrast per outcome metric (resting
  heart rate, HRV, sleep, steps, weight, basal/wrist/skin temperature),
  surfacing one headline finding (resting-heart-rate-by-phase, falling
  back to HRV); and
- the continuous phase ordinal folded into the lagged-Pearson matrix.

Phase never reaches the general correlations route — the temperature
channels held out of the general matrix are un-blocked only here, behind
the cycle gate, so a reproductive inference can never leak onto a
non-gated surface. Every row shows n, effect size, p and q; nothing is
fabricated on thin data and nothing is framed as causal.

Surface it through a new gated GET /api/cycle/insights and a drop-in
card that mirrors the mood-factor crosstab.

Add a cycle dimension to the Coach snapshot: current phase + day-of-cycle,
the next predicted event (period range + confidence + method, fertile
window goal-gated), and the headline phase finding — present only for a
cycle-enabled account, so a non-cycle snapshot is unchanged. A new ground
rule keeps the Coach descriptive: never contraception-grade, never a
"safe day" claim.

OpenAPI regenerated; phase-correlation + snapshot-inclusion tests added;
copy localised across all six locales.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 09:59:02 +02:00
Marc-André BombeckandClaude Opus 4.8 5f485ca780 feat(cycle): add cycle-tracking API surface + offline sync
Add the `/api/cycle/*` capture, calendar, history, and settings routes
plus the offline-sync delta extension for the v1.15 cycle-tracking
feature, all against the locked iOS contract.

- Enable flag: add nullable `cycleTrackingEnabled` to CycleProfile
  (migration 0132). A null toggle derives from gender (FEMALE → on).
  `isCycleEnabled()` is the single gate resolver; every `/api/cycle/*`
  route 403s `{ errorCode: "cycle.disabled" }` when off. The resolved
  flag surfaces additively on GET /api/auth/me.
- Routes (apiHandler + Zod + envelope + gate + annotate + auditLog):
  POST/PATCH/DELETE day-logs (single), POST day-logs/bulk (idempotent,
  capped 500, rate-limited 60/min, per-entry inserted/updated/duplicate/
  skipped), POST period boundary, GET calendar (runs the deterministic
  engine, debounced stale-while-revalidate cache, goal-gated fertile
  window), GET cycles (history + median/MAD stats), GET profile,
  DELETE cycles, PATCH /api/auth/me/cycle-prefs (deep-merge).
- Day-log note encrypts at rest (notesEncrypted); intent fields stay
  queryable plaintext. Upsert keys on (userId, source, externalId) when
  externalId present, else (userId, date).
- Offline sync: extend GET /api/sync/changes + the cursor with the
  `cycleDays` + `cycles` domains (CURSOR_VERSION → 2). cycleDays
  tombstones key on externalId else id; cycles on id.
- OpenAPI: register every route + DTO; regenerate the committed spec.
- i18n: cycle prediction disclaimer across all six locales.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 08:57:12 +02:00
Marc-André BombeckandClaude Opus 4.8 397e0d1b68 chore(release): v1.14.0 — animated health scores, score explanations, mood-factor correlations, log past doses
- The health-score strip is rebuilt as a calm, staggered signature reveal with
  a distinct colour per score, a soft glow, and a "vs your normal" reference
  arc — once per visit, reduced-motion-safe.
- Each Readiness / Sleep / Recovery / Strain / Stress score sheet carries a
  short plain-language explanation of why the score landed where it did
  (additive `assessment` field on the derived endpoint; fills without a
  provider).
- Rated mood factors (work / sleep quality / stress …) are correlated against
  vitals as a new card the assistant can cite — confidence-gated, observational.
- Medications "Add" splits into log-intake (incl. backdated) vs new medication;
  sparse weekly/rolling meds show an open-cycle status line instead of a bare
  percentage.
- Insights polish: equal-height trend cards, briefing heading above the card,
  coach tone + length side by side.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 00:23:52 +02:00
Marc-André BombeckandClaude Opus 4.8 30a7437f4d feat(insights): per-score assessment text + shared metric signal block
Add an additive, non-breaking assessment field to GET /api/insights/derived:
{ text, source, updatedAt } | null, keyed to the requested metric id for the
five per-score ids (READINESS, SLEEP_SCORE, RECOVERY_SCORE, STRAIN_SCORE,
STRESS_SCORE). The field is null when the metric is not one of those or when
its status is not "ok". A deterministic text always fills it — composed from
the score's own contributors, so provider-less accounts and the demo are never
empty — and warmer provider prose overrides it once cached, warmed out of band
so the GET never blocks on a model round-trip. de/en, following the v1.12.12
deterministic-narrative model. The batch grid read returns assessment: null;
the detail sheets use the single-metric route.

Introduce a shared buildMetricSignal() helper: a token-lean, signal-rich
descriptor (current, own baseline, signed delta, spread, normal-swing verdict,
normal-range placement, contributors) computed server-side so the model states
the comparison instead of re-deriving it from raw buckets. Thread it into the
generic per-metric assessment snapshot and lead the base prompt from it. Add a
PROMPT_VERSION constant to the base system prompt so prompt changes are
traceable.

Regenerate docs/api/openapi.yaml.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 23:57:39 +02:00
Marc-André BombeckandClaude Opus 4.8 b5e106776f chore(release): v1.13.3 — health score rates blood pressure again, steps in Insights
- Health score reads the all-time blood-pressure-in-range rate (not the trailing
  30 days), so an account with BP history but no recent readings keeps its BP
  pillar instead of showing "no rating"; the 30-day rate still drives the tile
  headline. (Regression from the v1.8.7 BP-headline window change.)
- ACTIVITY_STEPS now has its own Insights sub-page + nav entry (it was tracked +
  on the dashboard but absent from the Insights metric registry).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 22:53:15 +02:00
Marc-André Bombeck 016f866965 fix(insights): health-score BP pillar from all-time window + surface ACTIVITY_STEPS in Insights 2026-06-05 22:47:46 +02:00
Marc-André BombeckandClaude Opus 4.8 25bed4262c chore(release): v1.13.2 — honest weekly-med compliance, correct sleep average, calmer wellness scores
- Rolling-cadence (weekly GLP-1 injection) compliance now reconstructs the full
  per-cycle history across the window instead of counting only the next-due dose,
  so a faithful injection history reads an honest rate, not a 0%/100% flip; adds a
  per-medication currentCycle state (on_track/due/missed/none) for a non-scary card.
- Sleep average reads from the de-duplicated per-night reconstruction (bare ASLEEP +
  granular stages no longer double-count → no impossible ~20 h); night reconstruction
  hardened against an empty-segment throw.
- Wellness-score tiles redesigned: gentle card-toned surface (was a saturated slab),
  a larger thinner custom SVG ring with a soft per-score gradient, renamed
  "Your health scores", fully legible in light + dark.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 22:27:27 +02:00
Marc-André Bombeck a55816bf58 fix(medications): retrospective rolling-cadence compliance + currentCycle descriptor 2026-06-05 22:09:06 +02:00
Marc-André BombeckandClaude Opus 4.8 d3d58a0c30 chore(release): v1.13.1 — wellness rings fill to the actual score
The score-ring's RadialBar swept the full circle for any value because the
angular domain was only pinned on the PolarRadiusAxis (which governs radius,
not sweep). Recharts then auto-scaled the angular domain to the single datum,
so every ring read as 100%. Add a PolarAngleAxis with a fixed [0,100] number
domain so the bar sweeps value-percent of the track. Affects the overview
wellness tiles and the score-anatomy detail view.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 21:18:52 +02:00
Marc-André BombeckandClaude Opus 4.8 f1329b24e1 chore(release): v1.13.0 — per-user custom mood tags + catalogue hide
Let a user shape their own mood-tag set on top of the global catalogue:
create custom tags (label encrypted at rest, icon from a fixed allow-list),
and hide built-in tags per user. Custom tags live in `mood_tags` with a
non-null `user_id` and a `custom:<uuid>` key; `GET /api/mood/tags` returns
the effective per-user set (catalogue − hidden + own customs) with new
`custom` + `label` fields, and `?include=hidden` surfaces hidden catalogue
tags for the management screen. The write path resolves a `custom:` key only
against the caller's own rows — a foreign custom key is dropped, never linked.
Delete soft-deactivates by default (history intact); `?purge=true` removes
the row and its links. BINARY-only for v1.

New: POST/PATCH/DELETE /api/mood/tags/custom[/:key], PUT /api/mood/tags/:key/hidden,
migration 0127 (user_id + label_encrypted columns, mood_tag_hidden table,
`custom` category). Integration setup snapshots + restores the seeded catalogue
because the new mood_tags→users FK makes TRUNCATE users CASCADE wipe it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 20:50:05 +02:00
Marc-André BombeckandClaude Opus 4.8 f25b6aa2dc chore(release): v1.12.12 — deterministic fallback so the period retrospective is never empty
When no AI provider is configured (or before the first AI summary is written),
the period-in-review card stayed empty. Compose a concise, factual, strictly
non-causal summary from the same structured digest the AI prompt is built from
— ranked metric changes vs the prior period, vitals that moved outside their
typical range, and an honest count of statistical associations — and persist it
with a `deterministic` provider marker so a later AI warm replaces it in place.
The read route now warms regardless of provider; the read-never-blocks posture
is unchanged. Fills the no-key demo's retrospective too.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 19:10:08 +02:00
Marc-André BombeckandClaude Opus 4.8 038be6ac57 chore(release): v1.12.11 — unify settings notice colours and callout style
Route every Settings callout, badge and status note through the semantic
colour tokens (success / warning / info / primary) instead of raw palette
classes, so the same meaning reads identically across cards and stays
legible in light mode. Add a single SettingsInfoTile primitive — icon +
tone + text on one fixed surface — and adopt it for the threshold-override
caution note, replacing a bespoke box.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 18:42:18 +02:00
Marc-André Bombeck a15766a418 chore(release): v1.12.10 — a timeless taken-log no longer back-fills a far slot 2026-06-05 16:03:58 +02:00
Marc-André Bombeck 17be1084b1 chore(release): v1.12.9 — tighter mood catalogue, clearer cards, fixed retrospective 2026-06-05 15:40:04 +02:00
Marc-André Bombeck 186798a02f chore(release): v1.12.8 — fuller WHOOP data, charts that follow your selection 2026-06-05 14:58:08 +02:00
Marc-André BombeckandClaude Opus 4.8 de732ba732 docs(api): regenerate OpenAPI for new MeasurementType values
Pick up AVERAGE_HEART_RATE / MAX_HEART_RATE / SLEEP_DISTURBANCE_COUNT in the
MeasurementType enum the iOS client consumes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 14:46:14 +02:00
Marc-André Bombeck 7ce8868079 chore(release): v1.12.7 — Insights that react, read clean, and stay legible 2026-06-05 14:15:58 +02:00
Marc-André Bombeck 52f4417504 chore(release): v1.12.6 — one consistent Insights surface 2026-06-05 13:01:31 +02:00
Marc-André Bombeck 72146af6f9 chore(release): v1.12.5 — correct sleep summary and readiness contributors 2026-06-05 11:35:26 +02:00
Marc-André Bombeck f062a6016a chore(release): v1.12.4 — a calmer, more consistent Insights 2026-06-05 10:48:07 +02:00
Marc-André Bombeck bd22d68e03 chore(release): v1.12.3 — mark the dose you're looking at 2026-06-05 09:08:24 +02:00
Marc-André Bombeck 5d8a9799ac chore(release): v1.12.2 — WHOOP connect from the app, consistent assessments and medications 2026-06-05 08:21:00 +02:00
Marc-André Bombeck f531494c59 chore(release): v1.12.1 — security, data-integrity, and insight-quality hardening 2026-06-05 03:58:30 +02:00
Marc-André Bombeck 678ee80299 chore(release): v1.12.0 — Google Health sync, rated mood factors, Coach and insights overhaul 2026-06-05 01:19:38 +02:00
Marc-André Bombeck 86b2774567 feat(fitbit): add the Fitbit connection data model and FITBIT measurement source
Lay the data-model foundation for the Fitbit/Pixel integration over the
Google Health API, mirroring the WHOOP provider. No OAuth, sync, or UI yet.

- Prisma: FitbitConnection (1:1 per user, encrypted access/refresh tokens)
  and FitbitOAuthState models, two encrypted BYO-credential columns on User,
  and FITBIT appended to the MeasurementSource enum. Migration
  0117_v1120_fitbit_integration is additive only — one enum value plus two
  tables and two nullable columns, no new MeasurementType (every launch
  metric maps onto an existing type).
- Wire the two new encrypted columns and the FitbitConnection token columns
  into scripts/rotate-encryption-key.ts.
- FITBIT touchpoints: the read measurementSourceEnum (not the writable set),
  the DEFAULT_SOURCE_PRIORITY and workout-source ladders, the sources-section
  label map, the IntegrationKey union plus its display name, and a
  fitbit()/fitbitStatus() query-key pair. The source-rank SQL and read-tier
  collapse pick FITBIT up from the ladders with no code change.
- Add the FITBIT source label to all six locale bundles and regenerate the
  OpenAPI contract so the source enum carries FITBIT for the iOS decoder.
2026-06-04 21:02:10 +02:00
Marc-André Bombeck 9b8a7c98a0 chore(release): v1.11.5 — mood relations insights, sleep depth view, clear-the-decks polish 2026-06-04 19:43:27 +02:00
Marc-André Bombeck e4a85c58af feat(sleep): add the read-only sleep-night hypnogram endpoint
GET /api/sleep/night?date=YYYY-MM-DD returns one reconstructed night for
the phase-progression view: the canonical source's stage segments (each
with an absolute start/end span), the per-stage breakdown, the asleep/
in-bed/awake totals, the mid-sleep awakenings count, and same-wake-day
naps surfaced separately. Session-clustered, wake-day-keyed, one
canonical source per night so two sources never overlay. date omitted
returns the most recent night. A view over existing per-stage rows — no
schema, no new measurement type. OpenAPI regenerated.
2026-06-04 18:56:20 +02:00
Marc-André Bombeck cb4fd14a8a chore(release): v1.11.4 — sleep totals, trend captions, and a round of fixes 2026-06-04 17:27:12 +02:00
Marc-André Bombeck 3bc6124cf1 chore(release): v1.11.3 — WHOOP body data, quality-of-life polish, fuller translations 2026-06-04 15:58:51 +02:00
Marc-André BombeckandClaude Opus 4.8 074e3bbdf1 chore(release): v1.11.2 — Coach-memory controls, SSRF hardening, more pinnable metrics
Coach-memory management UI (review/forget durable facts), connect-time
DNS-rebinding pins on user/operator-overridable outbound hosts, eight
additional pinnable dashboard metrics, plus a rollup write-race fix and
fast-path source-priority amortisation.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 13:31:25 +02:00
Marc-André BombeckandClaude Opus 4.8 cb8568a2fd chore(release): v1.11.1 — source-aware vitals + Coach long-term memory
Closes the three v1.11.0 follow-ups: cross-source vital de-duplication
(measurement rollups resolve overlapping sources to the priority-ladder
canonical reading across charts, summaries, insights, and the live
fallback), the Coach's rolling encrypted conversation summary, and
durable encrypted personal facts with a list/forget surface.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 10:56:21 +02:00
Marc-André BombeckandClaude Opus 4.8 8e2e697370 feat(coach): facts management routes (list + forget)
Add the GDPR/trust surface for the durable Coach facts: GET lists the
caller's active facts decrypted, DELETE /[id] soft-deletes one, and a
bulk DELETE clears all — every verb apiHandler + requireAuth +
requireAssistantSurface("coach") + ownership-scoped, with an unknown or
cross-user id collapsing to an idempotent no-op that never leaks
existence. Registered in the OpenAPI contract.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 10:29:18 +02:00
Marc-André Bombeck df5f1d170b chore(release): v1.11.0 — WHOOP provider hub, longitudinal coach, clinician-grade FHIR record 2026-06-04 04:16:57 +02:00
Marc-André Bombeck e1cdbf3e06 chore(api): regenerate OpenAPI for the capabilities FHIR/share descriptors 2026-06-04 02:34:43 +02:00
Marc-André Bombeck 4afe1dc6d8 chore(api): regenerate OpenAPI for the trajectory derived metric 2026-06-04 01:40:48 +02:00
Marc-André Bombeck ceabf8a54d chore(api): regenerate OpenAPI for the FHIR and share-link routes 2026-06-04 01:05:15 +02:00
Marc-André Bombeck 86dea3e176 chore(api): regenerate OpenAPI for the WHOOP measurement types 2026-06-04 00:50:26 +02:00
Marc-André Bombeck b56f712d4e chore(release): v1.10.4 — strain honesty label + six-minute-walk reference caveat 2026-06-03 21:33:30 +02:00