Delete My Data, surfaced and irreversible #36

Closed
opened 2026-08-18 20:37:16 -05:00 by null · 1 comment
Owner

The deletion works and no user can reach it.

What is true now

CycleRepository.deleteAllHealthData() exists at core/data/src/main/kotlin/dev/privacyllc/period/core/data/CycleRepository.kt:250 and delegates to db.deleteEverything(). It is covered by an instrumented test in core/data/src/androidTest/.../PeriodCrudTest.kt. Nothing in the UI calls it.

What it costs

§45 requires Delete My Data to be clear and irreversible after confirmation, and the milestone lands only when it "actually deletes". Most of the work is done; what is missing is the part the user touches.

What to do

A Privacy & Security row, a confirmation that states plainly what is about to happen and cannot be dismissed by accident, and then the existing call.

Traps

  • Do not delete the user's privacy choices. core/datastore is deliberately a separate store from the cycle database precisely so that wiping health data cannot silently reset a notification-privacy setting the user chose — a person who wipes their history and then gets a Direct-mode reminder has been failed twice. Delete health data; leave UserPreferences alone, or ask separately.
  • Irreversible means no undo snackbar. An undo affordance on a destructive privacy action re-creates the data for the length of the timeout, which is the opposite of the promise.
  • A confirmation the user can tap through without reading is not a confirmation. §45 says clear.
  • If app lock ships first, deletion sits behind it — which is right, and worth checking rather than assuming.

Why filed and not fixed

The data-layer half is done; the surface needs the Settings screen, and the confirmation wording is copy that PRODUCT_PLAN.md owns.

Verify: The Privacy & Security row deletes every period, spotting and prediction record after an explicit confirmation, with no undo; the user's notification-privacy setting survives it; and re-opening the app shows the first-run empty state rather than a crash. Driven by hand, and PeriodCrudTest still passes.

The deletion works and no user can reach it. ## What is true now `CycleRepository.deleteAllHealthData()` exists at `core/data/src/main/kotlin/dev/privacyllc/period/core/data/CycleRepository.kt:250` and delegates to `db.deleteEverything()`. It is covered by an instrumented test in `core/data/src/androidTest/.../PeriodCrudTest.kt`. Nothing in the UI calls it. ## What it costs §45 requires Delete My Data to be clear and irreversible after confirmation, and the milestone lands only when it "actually deletes". Most of the work is done; what is missing is the part the user touches. ## What to do A Privacy & Security row, a confirmation that states plainly what is about to happen and cannot be dismissed by accident, and then the existing call. ## Traps - **Do not delete the user's privacy choices.** `core/datastore` is deliberately a separate store from the cycle database precisely so that wiping health data cannot silently reset a notification-privacy setting the user chose — a person who wipes their history and then gets a Direct-mode reminder has been failed twice. Delete health data; leave `UserPreferences` alone, or ask separately. - **Irreversible means no undo snackbar.** An undo affordance on a destructive privacy action re-creates the data for the length of the timeout, which is the opposite of the promise. - A confirmation the user can tap through without reading is not a confirmation. §45 says *clear*. - If app lock ships first, deletion sits behind it — which is right, and worth checking rather than assuming. ## Why filed and not fixed The data-layer half is done; the surface needs the Settings screen, and the confirmation wording is copy that `PRODUCT_PLAN.md` owns. Verify: The Privacy & Security row deletes every period, spotting and prediction record after an explicit confirmation, with no undo; the user's notification-privacy setting survives it; and re-opening the app shows the first-run empty state rather than a crash. Driven by hand, and `PeriodCrudTest` still passes.
null added this to the Batch 06 — Privacy and Security milestone 2026-08-18 20:37:16 -05:00
null added the
P1
label 2026-08-18 20:37:16 -05:00
null closed this issue 2026-08-18 21:03:19 -05:00
Author
Owner

Shipped in 8807951. SettingsScreen.kt has a Privacy & Security section whose confirmation states what is erased and what is kept, with no undo; PrivacyViewModel calls the existing CycleRepository.deleteAllHealthData(). PrivacyViewModelTest covers six cases including a double-tap while a delete is running. Driven on PeriodMinSdk26: set notification privacy to Maximum, deleted, and the setting survived — which is the claim the dialog makes. Today renders its empty state afterwards without crashing. Deliberately does NOT cancel the reminder schedule: ReminderWorker maps NoData to no decision, and cancelling would leave reminders off until the user next toggled a setting. 194 tests pass, ./gradlew check clean.

Shipped in 8807951. SettingsScreen.kt has a Privacy & Security section whose confirmation states what is erased and what is kept, with no undo; PrivacyViewModel calls the existing CycleRepository.deleteAllHealthData(). PrivacyViewModelTest covers six cases including a double-tap while a delete is running. Driven on PeriodMinSdk26: set notification privacy to Maximum, deleted, and the setting survived — which is the claim the dialog makes. Today renders its empty state afterwards without crashing. Deliberately does NOT cancel the reminder schedule: ReminderWorker maps NoData to no decision, and cancelling would leave reminders off until the user next toggled a setting. 194 tests pass, ./gradlew check clean.
Sign in to join this conversation.
No Label
P0
P1
P2
release-blocker
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: null/Privacy-Period-Tracker#36
No description provided.