Add iOS/Android microphone permission manifests
epic-structured-post-session-report-screen-task-006 — Add the NSMicrophoneUsageDescription key to Info.plist for iOS and the RECORD_AUDIO permission to AndroidManifest.xml for Android. Write the permission request rationale strings in both Norwegian Bokmål and English. Verify that the speech-to-text field overlay correctly triggers the runtime permission dialog before attempting to start recording, and that denial is handled gracefully without crashing.
Acceptance Criteria
Technical Requirements
Implementation Notes
Use the permission_handler package (^11.x) for cross-platform permission checking — do not call speech_to_text's initialize() before checking and receiving PermissionStatus.granted. Add NSMicrophoneUsageDescription to both Runner/Info.plist (for the main target) and any RunnerTests/Info.plist if tests require microphone. For Android, RECORD_AUDIO is a dangerous permission requiring a runtime dialog on API 23+; ensure it is in the main
Localised permission strings go in ios/Runner/nb.lproj/InfoPlist.strings and ios/Runner/en.lproj/InfoPlist.strings — the key is NSMicrophoneUsageDescription in both files.
Testing Requirements
Manual QA on physical devices (not simulator): iOS device — grant permission on first use; deny on first use; deny permanently and verify Settings redirect; re-grant from Settings and verify recording resumes. Android device — same four scenarios on Android 13+. Automated widget tests: SpeechToTextOverlay shows PermissionDeniedBanner when mock permission status is denied; shows PermissionSettingsRedirectDialog when status is permanentlyDenied; calls SpeechToText.listen() only after confirmed PermissionStatus.granted. Build verification: 'flutter build ios --no-codesign' completes without NSMicrophoneUsageDescription warnings; 'flutter build apk' includes RECORD_AUDIO in merged manifest.
End-to-end integration tests that span Flutter UI → Supabase → RLS → storage are inherently flaky in CI due to network timing, test database state, and Supabase cold-start latency. Flaky tests erode confidence and slow the release pipeline.
Mitigation & Contingency
Mitigation: Use a dedicated Supabase test project with seeded org and user fixtures. Wrap all E2E tests in retry logic with a fixed seed and tear-down hooks. Keep E2E tests in a separate test suite that runs on-demand rather than on every PR, with unit and widget tests as the primary CI gate.
Contingency: If E2E tests remain unreliable, replace the Supabase calls in integration tests with a verified fake (in-memory repository implementations) and promote the real Supabase tests to a nightly scheduled run rather than blocking PR merges.
Health status, course interest, and assistive device fields contain personal health data. If any logger, analytics event, or crash reporter captures field values — through automated error serialisation or developer-added debug logs — the feature could violate GDPR and Blindeforbundet's data processor agreement.
Mitigation & Contingency
Mitigation: Audit all log statements in the report feature's code paths before the epic is marked done. Apply a PII-safe logging wrapper that strips field values from any serialised form state before it reaches the logger. Add a CI lint rule that flags direct logger calls within report-related files.
Contingency: If PII is found in logs post-launch, immediately disable the affected logging call and rotate any credentials that were exposed. Notify the data protection officer and document the incident per GDPR Article 33 requirements.