From d2da8d2657a787100e614d1be9222b0113929bc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Sat, 6 Jun 2026 13:41:49 +0200 Subject: [PATCH] fix(cycle): reset reproductive intent on the data purge The hard-purge kept the CycleProfile row (so the gate + settings keep working) but left the intent-revealing fields behind. Reset goal to GENERAL_HEALTH and null the cycle/period/luteal priors inside the purge transaction so no reproductive intent survives, matching the route's "no reproductive trace persists" contract. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/app/api/cycle/all/route.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/app/api/cycle/all/route.ts b/src/app/api/cycle/all/route.ts index c5d508430..170586667 100644 --- a/src/app/api/cycle/all/route.ts +++ b/src/app/api/cycle/all/route.ts @@ -7,7 +7,9 @@ * menstrual cycles, predictions, the cycle audit trail, and the cycle * reminder-delivery rows in the push-attempts ledger — so no dated * reproductive trace survives in Postgres (the post-Dobbs threat model). The - * `CycleProfile` row is left in place (gate + settings keep working). + * `CycleProfile` row is left in place (gate + settings keep working) but its + * intent-revealing fields — goal + cycle/period/luteal priors — are reset to + * neutral defaults, so no reproductive intent survives either. * * Gated (`cycle.disabled` 403) and owner-scoped. The purge action itself IS * audited (written after the transaction, so it survives) — its `details` @@ -63,6 +65,18 @@ export const DELETE = apiHandler(async (request: NextRequest) => { eventType: { in: ["CYCLE_PERIOD_SOON", "CYCLE_PERIOD_CONFIRM"] }, }, }); + // Reset the reproductive INTENT carried on the profile (goal + cycle/period/ + // luteal priors) to neutral defaults so a purge leaves no intent-revealing + // state, while keeping the row so the gate + settings keep working. + await tx.cycleProfile.updateMany({ + where: { userId: user.id }, + data: { + goal: "GENERAL_HEALTH", + typicalCycleLength: null, + typicalPeriodLength: null, + lutealPhaseLength: null, + }, + }); return { dayLogs: dayLogs.count, predictions: predictions.count,