fix(cycle): carry every logged day entry on the calendar read

The calendar grid carried flow, symptoms, BBT, the ovulation test and the
mucus reading, and dropped the rest of the day log: intercourse, spotting,
the pregnancy and progesterone tests, contraception and whether a note
exists. The published contract also promised the three cervix signs while
the route never sent them.

The intent fields resolve through the same reader the day-log read uses,
so an encrypted envelope reads the same on both, and the grid is served
under the same cycle grant as the day log. Additive fields; the contract
test pins the wire keys to the published schema.
This commit is contained in:
Marc-André Bombeck committed 2026-09-25 07:02:14 +02:00
1 parent d81518b5bf
commit adec5bd045
7 files changed
+431 -31

No files matched your search

+18 -1
View File
@@ -186,7 +186,7 @@ const cyclePredictionDto = z
"The materialised forecast. Fertile-window fields (and predictedOvulation/ovulationConfirmed) are server-suppressed (null/false) unless the goal is TRYING_TO_CONCEIVE or AVOID_PREGNANCY.",
});
const cycleCalendarDayDto = z.object({
export const cycleCalendarDayDto = z.object({
date: z.string(),
phase: cyclePhaseEnumOpenapi.nullable(),
isPredictedPeriod: z.boolean(),
@@ -218,6 +218,23 @@ const cycleCalendarDayDto = z.object({
cervixPosition: cervixPositionEnum.nullable(),
cervixFirmness: cervixFirmnessEnum.nullable(),
cervixOpening: cervixOpeningEnum.nullable(),
// v1.39.1 — the rest of what a day log can hold, so a day with only one of
// these logged no longer reads as an empty day. Additive: an older client
// that does not know a field ignores it.
intermenstrualBleeding: z.boolean().meta({
description: "Spotting or bleeding outside the period logged on this day.",
}),
sexualActivity: z.boolean().meta({
description:
"Intercourse logged on this day. Resolved from the plaintext column or the encrypted envelope, exactly as the day-log read resolves it, and served under the same cycle grant.",
}),
pregnancyTest: homeTestResultEnumOpenapi.nullable(),
progesteroneTest: homeTestResultEnumOpenapi.nullable(),
contraceptive: z.string().nullable(),
hasNote: z.boolean().meta({
description:
"Whether the day carries a note. The note text is only on the day-log read.",
}),
});
const cycleVerdictDto = z