Summary
LocalDataControls now provides a visible "clear all local data" path, but the current implementation removes every byteflow:* localStorage key. That includes the explicit analytics opt-out key byteflow:analytics:opt-out.
If analytics is disabled today, the impact is latent. But the privacy contract should not depend on analytics staying disabled forever. A user who explicitly opted out should not lose that negative consent merely because they clear local app data.
Why this matters
Clear-data flows need special handling for consent and privacy preferences:
- Users generally expect "clear app data" to remove app state, cached preferences, recents, favorites, and saved recipes.
- Users do not expect it to silently re-enable tracking preferences they explicitly disabled.
- Byteflow's privacy posture depends on conservative handling of analytics and storage controls.
- The current analytics facade is no-op by design, but
isAnalyticsEnabled() is explicitly structured for a future provider; the opt-out semantics should be correct before any provider is introduced.
Current behavior
Relevant code path:
src/features/privacy/local-data-controls.tsxclearData() calls clearByteflowLocalData().- It then refreshes
analyticsOptedOut from isAnalyticsOptedOut().
src/core/storage/tool-persistence-policy.tsclearByteflowLocalData() iterates over window.localStorage and removes all keys that start with byteflow:.
src/core/analytics/preferences.ts- The analytics opt-out key is
byteflow:analytics:opt-out.
So a user who opted out of analytics can click "clear all local data" and lose the opt-out flag.
There is a similar completeness gap for session data: clearByteflowLocalData() only clears localStorage, while runtime code also uses window.sessionStorage for safe UI state such as byteflow:pwa-install:session-prompted.
Expected behavior
The clear-data behavior should distinguish between:
- App data that should be cleared:
- favorites;
- recent tools;
- tool preferences;
- PWA prompt state if appropriate;
- saved Pipeline recipes;
- Byteflow-owned sessionStorage keys.
- Explicit negative consent / privacy preference that should be preserved by default:
Suggested implementation plan
- Replace
clearByteflowLocalData() with a more explicit API, for example:
clearByteflowBrowserData({preserveAnalyticsOptOut: true,includeSessionStorage: true,})- Preserve
getAnalyticsOptOutStorageKey() by default when clearing all local data. - Add a separate explicit action only if you want users to reset analytics preference to default.
- Clear Byteflow-owned sessionStorage keys as part of the all-data clear path, except for any intentionally preserved privacy/consent keys.
- Update Local Data Controls copy so users understand that privacy opt-out is preserved unless explicitly changed.
- Add tests covering:
- analytics opt-out survives clear-all;
- non-consent
byteflow:* localStorage keys are removed; - Byteflow sessionStorage keys are removed;
- saved recipes are still cleared;
- the analytics checkbox state remains opted out after clear-all.
Acceptance criteria
Related code pointers
src/features/privacy/local-data-controls.tsxsrc/core/storage/tool-persistence-policy.tssrc/core/analytics/preferences.tssrc/components/layout/app-runtime.tsx
Summary
LocalDataControlsnow provides a visible "clear all local data" path, but the current implementation removes everybyteflow:*localStorage key. That includes the explicit analytics opt-out keybyteflow:analytics:opt-out.If analytics is disabled today, the impact is latent. But the privacy contract should not depend on analytics staying disabled forever. A user who explicitly opted out should not lose that negative consent merely because they clear local app data.
Why this matters
Clear-data flows need special handling for consent and privacy preferences:
isAnalyticsEnabled()is explicitly structured for a future provider; the opt-out semantics should be correct before any provider is introduced.Current behavior
Relevant code path:
src/features/privacy/local-data-controls.tsxclearData()callsclearByteflowLocalData().analyticsOptedOutfromisAnalyticsOptedOut().src/core/storage/tool-persistence-policy.tsclearByteflowLocalData()iterates overwindow.localStorageand removes all keys that start withbyteflow:.src/core/analytics/preferences.tsbyteflow:analytics:opt-out.So a user who opted out of analytics can click "clear all local data" and lose the opt-out flag.
There is a similar completeness gap for session data:
clearByteflowLocalData()only clears localStorage, while runtime code also useswindow.sessionStoragefor safe UI state such asbyteflow:pwa-install:session-prompted.Expected behavior
The clear-data behavior should distinguish between:
Suggested implementation plan
clearByteflowLocalData()with a more explicit API, for example:getAnalyticsOptOutStorageKey()by default when clearing all local data.byteflow:*localStorage keys are removed;Acceptance criteria
byteflow:analytics:opt-outwhen the user opted out.npm run test -- tests/component/privacy-page.test.tsxpasses.npm run test -- tests/guards/sensitive-storage-audit.test.ts tests/guards/verification-mode-acceptance.test.tspasses if updated.npm run check:typesandnpm run lintpass.Related code pointers
src/features/privacy/local-data-controls.tsxsrc/core/storage/tool-persistence-policy.tssrc/core/analytics/preferences.tssrc/components/layout/app-runtime.tsx