From 63a93486292fbe5e9361ccf5d93cba791c1e08c2 Mon Sep 17 00:00:00 2001 From: npub1ft62tztwwm2x9xamk25smmuaj4sfckdkldksruf2x2jwqalffkrq0g7arr <4af4a5896e76d4629bbbb2a90def9d95609c59b6fb6d01f12a32a4e077e94d86@sprout-oss.stage.blox.sqprod.co> Date: Sun, 19 Jul 2026 14:17:34 -0700 Subject: [PATCH] fix(mobile): preserve diagnostics revocation Co-authored-by: npub1ft62tztwwm2x9xamk25smmuaj4sfckdkldksruf2x2jwqalffkrq0g7arr <4af4a5896e76d4629bbbb2a90def9d95609c59b6fb6d01f12a32a4e077e94d86@sprout-oss.stage.blox.sqprod.co> Signed-off-by: npub1ft62tztwwm2x9xamk25smmuaj4sfckdkldksruf2x2jwqalffkrq0g7arr <4af4a5896e76d4629bbbb2a90def9d95609c59b6fb6d01f12a32a4e077e94d86@sprout-oss.stage.blox.sqprod.co> --- mobile/lib/features/settings/settings_page.dart | 4 ++-- .../lib/shared/diagnostics/diagnostics_controller.dart | 8 ++++++++ mobile/test/features/settings/settings_page_test.dart | 9 +++++++++ .../shared/diagnostics/diagnostics_controller_test.dart | 6 +++--- 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/mobile/lib/features/settings/settings_page.dart b/mobile/lib/features/settings/settings_page.dart index c3738d332..8975633db 100644 --- a/mobile/lib/features/settings/settings_page.dart +++ b/mobile/lib/features/settings/settings_page.dart @@ -117,8 +117,8 @@ class SettingsPage extends HookConsumerWidget { title: 'Share Crash Reports', subtitle: diagnostics.isConfigured ? 'Send crash details to help improve Buzz. Reports ' - 'exclude message text, screenshots, and personal ' - 'information.' + 'do not include screenshots, view hierarchy, ' + 'breadcrumbs, or performance traces.' : 'Crash reporting is unavailable in this build.', subtitleMaxLines: 4, trailing: Switch.adaptive( diff --git a/mobile/lib/shared/diagnostics/diagnostics_controller.dart b/mobile/lib/shared/diagnostics/diagnostics_controller.dart index 7ec561485..522a3d3da 100644 --- a/mobile/lib/shared/diagnostics/diagnostics_controller.dart +++ b/mobile/lib/shared/diagnostics/diagnostics_controller.dart @@ -70,6 +70,7 @@ class DiagnosticsController extends ChangeNotifier { } final previousConsent = _consentGranted; + var consentPersisted = false; _consentGranted = granted; notifyListeners(); try { @@ -80,8 +81,15 @@ class DiagnosticsController extends ChangeNotifier { if (!persisted) { throw StateError('Failed to persist diagnostics consent'); } + consentPersisted = true; await _applyCurrentConsent(); } on Object { + // A persisted revocation must survive teardown failure. Otherwise the + // next launch could initialize crash reporting against the user's + // explicit choice. + if (!granted && consentPersisted) { + rethrow; + } _consentGranted = previousConsent; final rolledBack = await _preferences.setBool( diagnosticsConsentPreferenceKey, diff --git a/mobile/test/features/settings/settings_page_test.dart b/mobile/test/features/settings/settings_page_test.dart index aeceebb13..3d04a9d95 100644 --- a/mobile/test/features/settings/settings_page_test.dart +++ b/mobile/test/features/settings/settings_page_test.dart @@ -56,6 +56,15 @@ void main() { expect(find.text('DIAGNOSTICS'), findsOneWidget); expect(find.text('Share Crash Reports'), findsOneWidget); + expect( + find.text( + 'Send crash details to help improve Buzz. Reports do not include ' + 'screenshots, view hierarchy, breadcrumbs, or performance traces.', + ), + findsOneWidget, + ); + expect(find.textContaining('personal information'), findsNothing); + expect(find.textContaining('message text'), findsNothing); final toggle = tester.widget(find.byType(Switch)); expect(toggle.value, isFalse); diff --git a/mobile/test/shared/diagnostics/diagnostics_controller_test.dart b/mobile/test/shared/diagnostics/diagnostics_controller_test.dart index e9c7d227d..09712430c 100644 --- a/mobile/test/shared/diagnostics/diagnostics_controller_test.dart +++ b/mobile/test/shared/diagnostics/diagnostics_controller_test.dart @@ -174,7 +174,7 @@ void main() { expect(reporter.initializeCalls, 1); }); - test('close failure rolls back revocation', () async { + test('close failure preserves persisted revocation', () async { final controller = await createController( storedValues: {diagnosticsConsentPreferenceKey: true}, ); @@ -183,8 +183,8 @@ void main() { await expectLater(controller.setConsent(false), throwsA(isA())); - expect(controller.consentGranted, isTrue); - expect(preferences.getBool(diagnosticsConsentPreferenceKey), isTrue); + expect(controller.consentGranted, isFalse); + expect(preferences.getBool(diagnosticsConsentPreferenceKey), isFalse); expect(reporter.closeCalls, 1); });