Repository navigation
feat: add user data export and privacy controls (#200) - #232
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
mudabs
left a comment
There was a problem hiding this comment.
Thank you, Nayira, for adding the user data export and privacy controls.
Please address these items before merge:
- Derive the displayed consent status from consentStatus or the same validity rule used by the backend. Checking only user.consent_given can show consent as granted when data usage consent is false or the consent version is stale. Add coverage for invalid or withdrawn consent and confirm Account Settings remains accessible without health consent.
- Add an endpoint-level authorization test proving unauthenticated requests are rejected and authenticated exports are limited to the signed-in user.
- Confirm export coverage for stored profile photos and record metadata. The export currently includes only photo_url and omits fields such as questionnaire updated_at. Include eligible fields or document these exclusions clearly.
There was a problem hiding this comment.
Thank you, Nayira, for adding the user data export and privacy controls. CI is passing, but please address these items before approval:
- Derive the displayed consent status from the validated
consentStatusor the shared consent-validity helper. Add tests for withdrawn, incomplete, and stale-version consent while confirming Account Settings remains accessible. - Add endpoint-level authorization tests proving unauthenticated requests are rejected and authenticated exports remain scoped to the signed-in user.
- Include eligible questionnaire metadata such as
updated_at, or document the intentional exclusions clearly. Profile photo URL coverage is already present. - Update the Account test resources so tests assert translated text rather than raw translation keys.
Please push the fixes and request another review.
There was a problem hiding this comment.
Note
Copilot was unable to complete this review at the selected tier due to model policy or plan restrictions.
🟡 Changes recommended
The change still leaves a moderate test isolation issue in Account.test.jsx where URL.createObjectURL/URL.revokeObjectURL are overwritten and not restored by vi.restoreAllMocks(), risking leaked global stubs and order-dependent failures across the test suite.
1 open issue
What changed in this PR
This pull request adds an authenticated “export my data” feature end-to-end: a new backend endpoint to export the signed-in user’s stored data, plus an Account Settings “Privacy and your data” section (now accessible without health-consent gating) with localized, accessible status/error messaging.
Changes:
- Backend: add
GET /api/v1/users/me/data-exportto return a strictly-scoped export payload for the current user and sendCache-Control: no-store. - Frontend: add “Download my data” UI with loading/success/empty/error states and screen-reader announcements; move
/settings/accountoutside the health-consent gate (while remaining authenticated). - i18n + tests: add privacy/export/retention/consent strings for en/es/hi/ar/zh and add backend/frontend test coverage for export success/failure/empty and scoping/credential exclusion.
This pull request requires changes.
| File | Review notes / what changed |
|---|---|
frontend/src/services/authService.js |
Adds a client wrapper to call the new data-export endpoint. |
frontend/src/pages/settings/Account.test.jsx |
Adds UI tests for export success/empty/error; needs fixes for global URL mock restoration and brittle assertions against i18n keys. |
frontend/src/pages/settings/Account.jsx |
Implements the Privacy section and download flow; align authService import specifier to avoid mock/module-resolution issues. |
frontend/src/App.jsx |
Updates routing so Account Settings is reachable without health-consent gating (still behind auth). |
frontend/public/locales/zh/common.json |
Adds privacy/export/retention/consent strings (ZH). |
frontend/public/locales/hi/common.json |
Adds privacy/export/retention/consent strings (HI). |
frontend/public/locales/es/common.json |
Adds privacy/export/retention/consent strings (ES). |
frontend/public/locales/en/common.json |
Adds privacy/export/retention/consent strings (EN). |
frontend/public/locales/ar/common.json |
Adds privacy/export/retention/consent strings (AR). |
backend/tests/test_health_summary.py |
Adds backend tests for export scoping, credential exclusion, cache header behavior, and empty-history export. |
backend/src/main.py |
Adds the /api/v1/users/me/data-export endpoint and constructs an explicit export payload. |
Review effort: Balanced
|
Thanks for the review! All items are addressed: Consent status uses consentStatus from the backend, falling back to the shared userHasValidHealthConsent helper. Added tests for withdrawn, incomplete, declined and stale-version consent, and confirmed Account Settings stays accessible without health consent. |
mudabs
left a comment
There was a problem hiding this comment.
Thank you, Nayira, for addressing the previous privacy export feedback and getting CI green.
Please fix the remaining test isolation issue in frontend/src/pages/settings/Account.test.jsx. URL.createObjectURL and URL.revokeObjectURL are assigned directly in beforeEach, but vi.restoreAllMocks() does not restore direct assignments. Capture and restore the originals, or use restorable Vitest spies/stubs, then rerun the frontend tests and request another review.
This is required before approval because the stubs may leak into other test files and cause order-dependent failures.
|
|
Thanks! Fixed the test isolation issue. jsdom doesn't define URL.createObjectURL/revokeObjectURL, so vi.spyOn can't wrap them. The suite now saves the original property descriptors and restores them (or deletes them if they were absent) in afterEach. Added a test that runs after the suite and fails if a mock is still installed. I confirmed it fails against the old cleanup. All 127 frontend tests pass. |
mudabs
left a comment
There was a problem hiding this comment.
Thank you, Nayira, for addressing the requested consent, authorization, metadata, localization, and test-isolation fixes.
I verified that the URL object stubs are now restored correctly, all CI checks pass, and the export remains scoped to the authenticated user. This PR is approved for merge. Please update the outdated stacked PR note before merging.




Summary
Lets users download a copy of their stored health data from Account Settings and explains how the app currently handles retention, deletion, and consent.
Closes #200
Changes Made
GET /api/v1/users/me/data-export. It returns only the signed-in user's profile, consent record, submitted questionnaires, and saved risk assessments.Cache-Control: no-store./settings/accountoutside the health-consent gate, so users who haven't given (or no longer have) health consent can still export their data.Testing
Checklist
Additional Notes