Commit Graph
2 Commits
Author SHA1 Message Date
Marc-André Bombeck 3bb130d4a1 fix(validation): stop a future timestamp emitting a spurious past-bound error
Review follow-up to the shared entry-instant guard. The past-floor refine
re-ran the full plausibility predicate, so a future-dated instant tripped
both refines and the 422 carried a nonsensical "too far in the past" message
alongside the correct future one. The floor refine now checks the past bound
alone; a future value emits only the future message, matching the pre-refactor
single-message contract.

Also harden the Health-Score BP inputs and de-duplicate the tile-window
derivation surfaced in the same review:

- the prior-week graded score now keys off the prior-week window's own
  sufficiency rather than the current window's, so the week-over-week graded
  delta never pairs a confident current value against a thin-sample prior one;
- the BD-Zielbereich 90-day count + effective span derive through one shared
  `deriveBpWindow90` helper, so the dashboard snapshot and the analytics thick
  slice can never compute the gate or the label span differently.
2026-06-14 13:59:56 +02:00
Marc-André Bombeck 3e7aa49eb0 feat(validation): bound entry timestamps with a shared plausibility guard
Only medication intake bounded its capture instant — a hand-rolled POST or a
faulty import could backdate a measurement to epoch zero or forward-date a
mood entry into next year, and both sailed through validation.

Extract the intake bound into a shared `validateEntryInstant` helper: reject
any instant more than a five-minute clock-skew tolerance in the future, and
reject anything before a 1900 far-past floor. Callers can clamp the past
window tighter — medication intake keeps its five-year floor — and override
the past-bound message to preserve an established contract.

Apply it to the measurement create/edit schema (`measuredAt`), the mood
schema (`moodLoggedAt`), and the cycle period + day-log (`loggedAt`);
medication intake now delegates to the same helper. The capture forms gain a
matching `max` on the datetime picker so a future instant can't be selected
in the UI either. The wire shape is unchanged, so the OpenAPI contract holds.
2026-06-14 13:51:51 +02:00