Content
View differences
Updated by Yan Zubrytskyi 21 days ago
### User Story
**As an** app user
**I want to** opt in or out of sharing crash reports (including a Firebase installation ID)
**so that I** can control what diagnostic data is collected about my app usage.
### Acceptance Criteria
* Immediately **after a successful login** (or when connecting On app launch after updating to a new instance) for version that introduces or changes crash report collection, the first time after the update, the app shows an opt-in modal titled “Help **“Help us improve app stability”. stability”**.
* The modal body explains that crash reports are collected to fix bugs and improve performance.
* The modal explicitly states that the Firebase installation ID is used only to understand how many users are affected.
* The modal explicitly states that only an anonymous statistic is used as the outcome of crash counting.
* The modal contains a single checkbox with the label **“I agree to share crash reports to help improve the app.”**
* The checkbox is **unchecked by default**.
* The modal contains a **Privacy Policy** link, styled as a link and tappable.
* Tapping the **Privacy Policy** link opens the privacy policy content in an in-app browser or system browser.
* The modal contains two actions:
* **Confirm** (primary)
* **X** button on the top corner (copy confirm action)
* Tapping **X** dismisses the modal without changing the previously stored crash-report consent value.
* Tapping **Done** stores the crash-report consent value based on the checkbox state:
* Checked means consent is set to “opted in”.
* Unchecked means consent is set to “opted out”.
* After tapping **Done**, the modal dismisses.
* If the user closes the modal via the close icon (X), the behavior matches **Close** (no consent value change).
* The consent choice is persisted locally and **associated with the specific account/instance**.. restored on next app launch.
* The app applies the stored consent choice **immediately after the account is identified**, on startup before any crash reporting is enabled for that session.. initialized or enabled.
* Crash report collection is disabled when the stored consent is “opted out”.
* Crash report collection is enabled when the stored consent is “opted in”.
* The modal can be re-opened at any time from **Settings → Crash reports opt-in**.
* Re-opening the modal from Settings pre-fills the checkbox to reflect the currently stored consent value.
* If the user changes the checkbox and taps **Done** when opened from Settings, the new consent value is stored and takes effect immediately for subsequent crash events.
* If there is no stored consent value (first run after update), the Settings entry still opens the modal and shows the checkbox unchecked.
* The Settings screen includes a visible entry “Crash **“Crash reports opt-in” opt-in”** (or equivalent) and it is accessible **to all authenticated users**. without requiring authentication beyond the app’s normal access.
* The modal layout supports small screens without clipping content, with scroll behavior if needed.
* <br>
* The app does not prompt again automatically after the user has explicitly set a consent value, unless a future app version introduces a materially new purpose or data category requiring renewed consent.
* If the user is not logged in (e.g., on the login screen), the modal is not shown and crash collection remains disabled.
### Technical Notes
* Assumptions:
* Crash reporting is implemented using Firebase Crashlytics (or equivalent Firebase crash reporting tooling).
* The referenced “Firebase installation ID” corresponds to the Firebase Installation ID (FID), not an advertising identifier.
* Data model implications:
* Persist a single boolean or enum value, e.g. `crashReportsConsent = opted_in | opted_out | unknown`.
* Persist a timestamp and app version when consent was last set, e.g. `crashReportsConsentUpdatedAt`, `crashReportsConsentSetInVersion` (optional but recommended for audits and future re-consent logic).
* Backend vs frontend responsibilities:
* Mobile app is responsible for rendering the modal, storing consent, and enabling or disabling crash reporting SDK initialization/collection.
* No backend changes required unless the app also forwards crash logs to a proprietary backend.
* SDK behavior considerations:
* Ensure crash reporting is disabled by default until consent is explicitly opted in (when consent is `unknown` treat as `opted_out` for collection).
* Apply consent as early as possible at app startup, before crash SDK starts sending reports.
* If the SDK supports runtime toggling, apply changes immediately on **Done** from Settings.
* Privacy policy link:
* Use a single immutable URL per environment: `https://www.openproject.org/legal/privacy/`
* Consider locale-aware URL routing if privacy policy is localized.
* Caching, state, and performance:
* Consent read should be synchronous or near-instant (local storage).
* Avoid any network calls to determine whether to show the modal.
* Risks and constraints:
* Some crash SDKs may collect minimal device/app metadata even when disabled unless explicitly configured. Confirm the exact “disabled” behavior and ensure it meets legal requirements.
* If the app crashes before the user sets consent, crash reports must not be uploaded when consent is unknown.
* If the modal is shown as an overlay on Settings (as in the mockups), ensure it is accessible and does not trap navigation.
### Permissions and Visibility Considerations
* All users must see at least once the opt-in modal
* The Settings entry to re-open the modal is visible to all users
* If the app supports multiple accounts on a single device:
* Crash report consent is an account-level consent
* The modal is always accessible through Settings, regardless of current consent states
### Translation Considerations
* Strings requiring localisation:
* “Help us improve app stability”
* Modal body text describing crash report collection, crash type/time, Firebase installation ID usage, and anonymous statistic statement
* “I agree to share crash reports to help improve the app.”
* “You can change this choice at any time in your account settings.”
* “Learn more in our Privacy Policy.”
* Settings labels: “Crash reports opt-in”
* Must NOT be translated:
* “Firebase”
* “Firebase installation ID”
* Any URLs (privacy policy URL)
* Any internal keys/identifiers used in code (e.g. `crashReportsConsent`)
### Out of Scope
* Changing the content of the privacy policy itself.
* Implementing a full consent management centre beyond the crash reports opt-in.
* Adding additional analytics or marketing tracking consent flows.
**As an** app user
**I want to** opt in or out of sharing crash reports (including a Firebase installation ID)
**so that I** can control what diagnostic data is collected about my app usage.
### Acceptance Criteria
* Immediately **after a successful login** (or when connecting
* The modal body explains that crash reports are collected to fix bugs and improve performance.
* The modal explicitly states that the Firebase installation ID is used only to understand how many users are affected.
* The modal explicitly states that only an anonymous statistic is used as the outcome of crash counting.
* The modal contains a single checkbox with the label **“I agree to share crash reports to help improve the app.”**
* The checkbox is **unchecked by default**.
* The modal contains a **Privacy Policy** link, styled as a link and tappable.
* Tapping the **Privacy Policy** link opens the privacy policy content in an in-app browser or system browser.
* The modal contains two actions:
* **Confirm** (primary)
* **X** button on the top corner (copy confirm action)
* Tapping **X** dismisses the modal without changing the previously stored crash-report consent value.
* Tapping **Done** stores the crash-report consent value based on the checkbox state:
* Checked means consent is set to “opted in”.
* Unchecked means consent is set to “opted out”.
* After tapping **Done**, the modal dismisses.
* If the user closes the modal via the close icon (X), the behavior matches **Close** (no consent value change).
* The consent choice is persisted locally and **associated with the specific account/instance**..
* The app applies the stored consent choice **immediately after the account is identified**,
* Crash report collection is disabled when the stored consent is “opted out”.
* Crash report collection is enabled when the stored consent is “opted in”.
* The modal can be re-opened at any time from **Settings → Crash reports opt-in**.
* Re-opening the modal from Settings pre-fills the checkbox to reflect the currently stored consent value.
* If the user changes the checkbox and taps **Done** when opened from Settings, the new consent value is stored and takes effect immediately for subsequent crash events.
* If there is no stored consent value (first run after update), the Settings entry still opens the modal and shows the checkbox unchecked.
* The Settings screen includes a visible entry “Crash
* The modal layout supports small screens without clipping content, with scroll behavior if needed.
* <br>
* The app does not prompt again automatically after the user has explicitly set a consent value, unless a future app version introduces a materially new purpose or data category requiring renewed consent.
* If the user is not logged in (e.g., on the login screen), the modal is not shown and crash collection remains disabled.
### Technical Notes
* Assumptions:
* Crash reporting is implemented using Firebase Crashlytics (or equivalent Firebase crash reporting tooling).
* The referenced “Firebase installation ID” corresponds to the Firebase Installation ID (FID), not an advertising identifier.
* Data model implications:
* Persist a single boolean or enum value, e.g. `crashReportsConsent = opted_in | opted_out | unknown`.
* Persist a timestamp and app version when consent was last set, e.g. `crashReportsConsentUpdatedAt`, `crashReportsConsentSetInVersion` (optional but recommended for audits and future re-consent logic).
* Backend vs frontend responsibilities:
* Mobile app is responsible for rendering the modal, storing consent, and enabling or disabling crash reporting SDK initialization/collection.
* No backend changes required unless the app also forwards crash logs to a proprietary backend.
* SDK behavior considerations:
* Ensure crash reporting is disabled by default until consent is explicitly opted in (when consent is `unknown` treat as `opted_out` for collection).
* Apply consent as early as possible at app startup, before crash SDK starts sending reports.
* If the SDK supports runtime toggling, apply changes immediately on **Done** from Settings.
* Privacy policy link:
* Use a single immutable URL per environment: `https://www.openproject.org/legal/privacy/`
* Consider locale-aware URL routing if privacy policy is localized.
* Caching, state, and performance:
* Consent read should be synchronous or near-instant (local storage).
* Avoid any network calls to determine whether to show the modal.
* Risks and constraints:
* Some crash SDKs may collect minimal device/app metadata even when disabled unless explicitly configured. Confirm the exact “disabled” behavior and ensure it meets legal requirements.
* If the app crashes before the user sets consent, crash reports must not be uploaded when consent is unknown.
* If the modal is shown as an overlay on Settings (as in the mockups), ensure it is accessible and does not trap navigation.
### Permissions and Visibility Considerations
* All users must see at least once the opt-in modal
* The Settings entry to re-open the modal is visible to all users
* If the app supports multiple accounts on a single device:
* Crash report consent is an account-level consent
* The modal is always accessible through Settings, regardless of current consent states
### Translation Considerations
* Strings requiring localisation:
* “Help us improve app stability”
* Modal body text describing crash report collection, crash type/time, Firebase installation ID usage, and anonymous statistic statement
* “I agree to share crash reports to help improve the app.”
* “You can change this choice at any time in your account settings.”
* “Learn more in our Privacy Policy.”
* Settings labels: “Crash reports opt-in”
* Must NOT be translated:
* “Firebase”
* “Firebase installation ID”
* Any URLs (privacy policy URL)
* Any internal keys/identifiers used in code (e.g. `crashReportsConsent`)
### Out of Scope
* Changing the content of the privacy policy itself.
* Implementing a full consent management centre beyond the crash reports opt-in.
* Adding additional analytics or marketing tracking consent flows.