Skip to content

Commit 7101f43

Browse files
committed
Merge remote-tracking branch 'origin/main' into codexd/445-full-screen-intent-declaration
# Conflicts: # docs/Release-Checklist.md
2 parents 860e145 + 53896d7 commit 7101f43

28 files changed

Lines changed: 2113 additions & 20 deletions
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
# Android Alarm And Notification QA
2+
3+
Use this runbook for release issue #457 after the app can be installed from a
4+
signed release AAB or release-equivalent Android build.
5+
6+
## Blockers
7+
8+
Do not mark #457 complete until these are satisfied:
9+
10+
- #452 provides a signed release AAB or release-equivalent install path.
11+
- #445 full-screen intent declaration material is reviewed or submitted by a
12+
human with Play Console access, per the parent track order.
13+
- QA has access to an Android device or emulator with Google Play services, a
14+
backend environment with alarm APIs enabled, and a test account that can create
15+
schedules.
16+
17+
## Source Context
18+
19+
- Android permissions: `docs/Android-Manifest-Permissions.md`
20+
- General native alarm checklist: `plans/native_alarm_platform_qa_checklist.md`
21+
- Native Android bridge: `android/app/src/main/kotlin/club/devkor/ontime/`
22+
- Dart reconciliation: `lib/domain/use-cases/reconcile_alarms_use_case.dart`
23+
- Alarm provider/status values: `lib/domain/entities/alarm_entities.dart`
24+
25+
## Device Matrix
26+
27+
Record every device used.
28+
29+
| Device | Android version | Install source | Backend env | Tester | Result |
30+
| --- | --- | --- | --- | --- | --- |
31+
| TBD | TBD | signed release AAB or release-equivalent install | TBD | TBD | TBD |
32+
33+
Minimum recommended coverage:
34+
35+
- Android 13 or newer for `POST_NOTIFICATIONS`.
36+
- Android 12 or newer for exact alarm special access.
37+
- One physical device for boot restore and full-screen alarm behavior.
38+
39+
## Permission Setup
40+
41+
Package name:
42+
43+
```sh
44+
PACKAGE=club.devkor.ontime
45+
```
46+
47+
Notification permission on Android 13+:
48+
49+
```sh
50+
adb shell pm grant "$PACKAGE" android.permission.POST_NOTIFICATIONS
51+
adb shell pm revoke "$PACKAGE" android.permission.POST_NOTIFICATIONS
52+
```
53+
54+
Exact alarm special access on Android 12+:
55+
56+
```sh
57+
adb shell appops set "$PACKAGE" SCHEDULE_EXACT_ALARM allow
58+
adb shell appops set "$PACKAGE" SCHEDULE_EXACT_ALARM deny
59+
adb shell appops get "$PACKAGE" SCHEDULE_EXACT_ALARM
60+
```
61+
62+
If the shell command is unavailable or ignored on the device, use Android
63+
Settings > Apps > Special app access > Alarms and reminders, then relaunch
64+
OnTime and re-run the scenario.
65+
66+
Avoid `pm clear` unless the tester intentionally wants to wipe local app data
67+
for the test account.
68+
69+
## Test Data
70+
71+
For each scenario, create or reuse a schedule whose alarm time is soon enough to
72+
observe without waiting through a long real-world route. Record:
73+
74+
| Field | Value |
75+
| --- | --- |
76+
| Schedule ID | TBD |
77+
| Schedule title | TBD |
78+
| Schedule time | TBD |
79+
| Expected preparation start/alarm time | TBD |
80+
| Account | TBD |
81+
| Backend environment | TBD |
82+
| App version/build | TBD |
83+
84+
## Scenarios
85+
86+
### 1. Notification Permission Granted
87+
88+
1. Grant `POST_NOTIFICATIONS`.
89+
2. Launch OnTime and sign in.
90+
3. Confirm notification permission copy is not blocking the app.
91+
4. Create a near-future schedule and allow alarm reconciliation to run.
92+
5. Record whether fallback or native alarm notifications can be shown.
93+
94+
Expected result: notification permission is treated as granted, and fallback
95+
notifications are available when native alarm scheduling cannot be used.
96+
97+
### 2. Notification Permission Denied
98+
99+
1. Revoke `POST_NOTIFICATIONS`.
100+
2. Launch OnTime and sign in.
101+
3. Exercise the allow-notification or My Page recovery path.
102+
4. Create a near-future schedule and allow alarm reconciliation to run.
103+
104+
Expected result: the app explains why schedule preparation reminders need
105+
notifications and does not post fallback notifications while permission is
106+
denied.
107+
108+
### 3. Exact Alarm Permission Granted
109+
110+
1. Allow `SCHEDULE_EXACT_ALARM`.
111+
2. Grant `POST_NOTIFICATIONS`.
112+
3. Create a near-future schedule.
113+
4. Background the app before the expected alarm time.
114+
5. Wait for the alarm.
115+
116+
Expected result: the native Android alarm provider is used, the alarm fires at
117+
the expected time, and the alarm path opens schedule preparation.
118+
119+
### 4. Exact Alarm Permission Denied With Notification Granted
120+
121+
1. Deny `SCHEDULE_EXACT_ALARM`.
122+
2. Grant `POST_NOTIFICATIONS`.
123+
3. Relaunch OnTime or toggle schedule alarms off and on in My Page.
124+
4. Create a near-future schedule and wait for the alarm time.
125+
126+
Expected result: the app explains precise alarm timing when recovery is needed,
127+
uses `localNotification` fallback where available, and records/reporting should
128+
show fallback behavior instead of native exact alarm scheduling.
129+
130+
### 5. Exact Alarm And Notification Denied
131+
132+
1. Deny `SCHEDULE_EXACT_ALARM`.
133+
2. Revoke `POST_NOTIFICATIONS`.
134+
3. Relaunch OnTime or toggle schedule alarms off and on in My Page.
135+
4. Create a near-future schedule.
136+
137+
Expected result: no native alarm or fallback notification is armed; the app
138+
surfaces permission recovery instead of silently claiming alarm coverage.
139+
140+
### 6. Full-Screen Alarm UI
141+
142+
1. Allow exact alarm special access and notification permission.
143+
2. Create a near-future schedule.
144+
3. Lock the device or put the app in the background.
145+
4. Wait for the alarm.
146+
5. Use the full-screen alarm action to start preparing.
147+
6. Repeat once and dismiss/cancel the ringing alarm instead of starting.
148+
149+
Expected result: `AlarmRingingActivity` appears only for the user-scheduled
150+
alarm moment, the start action routes into schedule preparation, and dismissal
151+
stops ringing/vibration and removes the alarm notification.
152+
153+
### 7. Cancellation
154+
155+
1. Create a near-future schedule with permissions granted.
156+
2. Before the alarm time, start preparation early, finish the schedule, delete
157+
the schedule, or disable schedule alarms in My Page.
158+
3. Wait past the original alarm time.
159+
160+
Expected result: no alarm or fallback notification fires after cancellation.
161+
162+
### 8. Boot Restore
163+
164+
1. Allow exact alarm special access and notification permission.
165+
2. Create a future schedule far enough out to reboot the device.
166+
3. Restart the device.
167+
4. Unlock and wait for the expected alarm time. If practical, also open OnTime
168+
once after boot to trigger app reconciliation.
169+
170+
Expected result: future native alarms are restored where Android permits boot
171+
restore, and any failure is recorded with the device model and Android version.
172+
173+
## Evidence Form
174+
175+
Attach this evidence to #457 or the release QA record.
176+
177+
| Item | Evidence |
178+
| --- | --- |
179+
| Device model | TBD |
180+
| Android version/API | TBD |
181+
| App version/build number | TBD |
182+
| Install source or artifact path | TBD |
183+
| Backend environment | TBD |
184+
| Test account | TBD |
185+
| Notification granted result | TBD |
186+
| Notification denied result | TBD |
187+
| Exact alarm granted result | TBD |
188+
| Exact alarm denied + notification granted result | TBD |
189+
| Exact alarm denied + notification denied result | TBD |
190+
| Full-screen alarm UI result | TBD |
191+
| Fallback notification result | TBD |
192+
| Cancellation result | TBD |
193+
| Boot restore result | TBD |
194+
| Failures and logs | TBD |
195+
| Screenshots/recordings | TBD |
196+
197+
## Failure Triage
198+
199+
For any failure, record:
200+
201+
- Scenario name and permission state.
202+
- Schedule ID, expected alarm time, actual observed time, and timezone.
203+
- Whether the app was foregrounded, backgrounded, terminated, locked, or after
204+
reboot.
205+
- Screenshot or screen recording.
206+
- Relevant `adb logcat` excerpt filtered to `OnTime`, `Alarm`, or
207+
`club.devkor.ontime`, without personal account data.
208+
- Whether the issue reproduces after reinstalling the same artifact.

docs/Android-Release-Configuration.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Android release builds must include the production Firebase client config so Fir
66

77
- `ANDROID_GOOGLE_SERVICES_JSON_B64`: base64-encoded contents of the production Android `google-services.json` for Firebase project `ontime-c63f1`.
88

9-
The release verification workflow decodes this secret to `android/app/src/release/google-services.json` before running the Android release build. Generated `google-services.json` files are ignored and must not be committed.
9+
The Android Play Internal Deploy workflow decodes this secret to `android/app/src/release/google-services.json` before running the Android release build. Generated `google-services.json` files are ignored and must not be committed.
1010

1111
The decoded file must include an Android client whose package name is `club.devkor.ontime`. Gradle validates this package match for release builds and through the focused validation task below.
1212

@@ -90,4 +90,4 @@ Release SHA-1 and SHA-256 fingerprints must be added to Firebase after the relea
9090

9191
## Verification
9292

93-
Use the `Android Release Verification` GitHub Actions workflow to confirm CI can reproduce the release build with the configured secret. For production readiness, also install a real Android release build and verify Firebase initializes and FCM token registration reaches the backend.
93+
Use the `Android Play Internal Deploy` GitHub Actions workflow to confirm CI can reproduce the signed release build with the configured secrets. For production readiness, also install a real Android release build and verify Firebase initializes and FCM token registration reaches the backend.

docs/Android-Signing-Setup.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ The Gradle build also accepts the legacy `ONTIME_ANDROID_KEYSTORE_PATH`,
7676
## Configure CI Release Signing
7777

7878
For GitHub Actions deploys, base64-encode the upload keystore and store it as
79-
the `ANDROID_UPLOAD_KEYSTORE_B64` secret in the protected `release`
80-
environment:
79+
the `ANDROID_UPLOAD_KEYSTORE_B64` secret in the protected `staging`
80+
environment used by the Android Play Internal Deploy workflow:
8181

8282
```sh
8383
base64 -i ~/secure/ontime-upload.jks | pbcopy

docs/Google-Play-Data-Safety.md

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
# Google Play Data Safety Worksheet
2+
3+
This worksheet advances release issue #441 under parent track #464. It is not a
4+
final Google Play declaration and must not be pasted into Play Console until the
5+
open prerequisites below are resolved.
6+
7+
## Status
8+
9+
Current status: externally blocked.
10+
11+
Blocking prerequisites:
12+
13+
| Input | Source issue | Status on 2026-05-10 | Why it blocks submission |
14+
| --- | --- | --- | --- |
15+
| Approved privacy policy text | #434 | Open, manual | Google Play requires a privacy policy and the Data safety answers must match it. |
16+
| Backend deletion and retention truth | #439 | Open, manual/backend | Data deletion support, retention exceptions, and associated data deletion are server-side facts. |
17+
| External account deletion request URL | #440 | Open, manual | Play requires an outside-app deletion path for apps with accounts. |
18+
| Manifest permission audit | #442 | Closed | Evidence is available in `docs/Android-Manifest-Permissions.md`. |
19+
| Final release SDK/provider set | #441 prerequisite | Pending owner confirmation | SDK data collection must match the shipped release build. |
20+
21+
Google's current guidance says developers are responsible for complete and
22+
accurate declarations, including data handled by third-party SDKs, and should
23+
review app permissions, APIs, SDK behavior, privacy policy, encryption, sharing,
24+
and deletion practices before submitting the form:
25+
26+
- https://support.google.com/googleplay/android-developer/answer/10787469
27+
- https://developers.google.com/android/guides/play-data-disclosure
28+
- https://firebase.google.com/docs/android/play-data-disclosure
29+
30+
## Source Evidence Reviewed
31+
32+
Repo evidence reviewed for this worksheet:
33+
34+
- `pubspec.yaml`
35+
- `lib/core/constants/endpoint.dart`
36+
- `lib/data/data_sources/authentication_remote_data_source.dart`
37+
- `lib/data/data_sources/schedule_remote_data_source.dart`
38+
- `lib/data/data_sources/preparation_remote_data_source.dart`
39+
- `lib/data/data_sources/alarm_remote_data_source.dart`
40+
- `lib/data/data_sources/notification_remote_data_source.dart`
41+
- `lib/data/data_sources/token_local_data_source.dart`
42+
- `lib/data/repositories/user_repository_impl.dart`
43+
- `lib/domain/entities/user_entity.dart`
44+
- `lib/domain/entities/schedule_entity.dart`
45+
- `lib/domain/entities/place_entity.dart`
46+
- `lib/domain/entities/alarm_entities.dart`
47+
- `docs/Android-Manifest-Permissions.md`
48+
- `docs/Release-Checklist.md`
49+
50+
## Current App Data Flow Inventory
51+
52+
This table maps current source evidence to likely Google Play Data safety review
53+
areas. Final categories, required or optional status, purposes, sharing, and
54+
deletion support must be approved by the release owner.
55+
56+
| Data flow | Current source evidence | Likely form area | Current confidence |
57+
| --- | --- | --- | --- |
58+
| Account sign-up and sign-in | Normal auth sends email, password, and name to `/login` and `/sign-up`; user responses include id, email, name, spare time, note, score. | Personal info, account management, app functionality | Source-backed, backend retention pending |
59+
| Google sign-in | Google auth requests `email` and `profile` scopes and sends an ID token to `/oauth2/google/login`. | Personal info and identifiers handled through Google sign-in | Source-backed, final provider set pending |
60+
| Apple sign-in | Apple auth requests email and full name scopes and sends ID token, auth code, full name, and optional email to `/oauth2/apple/login`. | Personal info and identifiers handled through Apple sign-in | Source-backed, final provider set pending |
61+
| Auth tokens | Access and refresh tokens are stored in `flutter_secure_storage` and sent as bearer authorization headers. | Security credential handling, not a Play user-facing data category by itself unless policy owner maps it | Source-backed, policy mapping pending |
62+
| Schedules | Schedule create/update sends schedule id, place id, place name, schedule name, schedule time, move time, spare time, started/change flags, and schedule note. | App activity, user-generated content, possible location/place information | Source-backed, final category mapping pending |
63+
| Preparation steps and spare time | Default and schedule preparation APIs send preparation ids, names, durations, ordering links, spare time, and note. | App activity or user-generated content | Source-backed, final category mapping pending |
64+
| Feedback and deletion feedback | Feedback endpoints send generated feedback id and free-text message; deletion can include optional feedback. | App activity or user-generated content, depending on final policy wording | Source-backed, backend retention pending |
65+
| Push notification registration | FCM token registration sends `firebaseToken` and app-generated `deviceId` to `/firebase-token`. | Device or other identifiers, app functionality | Source-backed, SDK disclosure pending |
66+
| Alarm device registration | Current device registration sends app-generated device id, platform, app version, OS version, native alarm support, and alarm providers. | Device or other identifiers, app info and performance | Source-backed, backend retention pending |
67+
| Alarm status reporting | Alarm status reports send device id, reconciliation timestamps, schedule window, coverage window, alarm provider, status, permission issue, armed schedule ids, skipped count, and failures. | App info and performance, diagnostics, device or other identifiers | Source-backed, backend retention pending |
68+
| Local alarm registry | Scheduled alarm records are stored locally with schedule id, alarm time, preparation start time, fingerprint, notification ids, provider, schedule title, and payload. | On-device storage; disclose only if transmitted or shared elsewhere | Source-backed |
69+
| Android permissions | Release manifest includes notification, exact alarm, full-screen intent, boot restore, vibration, and dependency-owned network/Firebase/sign-in permissions. It does not include location, contacts, camera, microphone, phone, SMS, storage, calendar, nearby-device, or Bluetooth permissions. | Permission/API evidence for form consistency | Source-backed by #442 |
70+
| Firebase Cloud Messaging SDK | The app uses `firebase_core` and `firebase_messaging`. Firebase documentation says Cloud Messaging collects app version automatically and depends on Firebase Installations; FID and Firebase user agent handling must be considered. | SDK-collected data, device or other identifiers, app info and performance | Source-backed dependency, final SDK review pending |
71+
| Google Play services core SDKs | Google Play services base/basement/tasks may be present through dependencies. Google's disclosure page says the listed core SDKs do not collect end-user data, but app owners remain responsible for the overall disclosure. | SDK review | Dependency review pending |
72+
73+
## Answers That Must Stay Pending
74+
75+
Do not finalize these fields until the owners listed below provide the missing
76+
facts.
77+
78+
| Field or decision | Required owner input |
79+
| --- | --- |
80+
| Whether each collected data type is required or optional | Product owner and source review. |
81+
| Whether any data is shared outside service-provider processing | Backend owner, Firebase/Google configuration owner, and privacy owner. |
82+
| Backend retention period for accounts, schedules, preparations, feedback, FCM tokens, device registrations, alarm status, and logs | Backend owner. |
83+
| Whether deletion requests delete or anonymize each associated data type, and within what time window | Backend owner and privacy owner. |
84+
| Whether any data is retained for legal compliance, security, abuse prevention, or operations | Backend owner and legal/product owner. |
85+
| Final privacy policy URL and exact text | Product/legal owner and #434/#435. |
86+
| External account deletion request URL and page content | Web/backend owner and #440. |
87+
| Final active auth providers for Android release | Release owner. Current source supports normal, Google, and Apple paths; Kakao dependencies are present but no active release flow was found in the checked auth path. |
88+
| Firebase optional exports such as FCM delivery metrics to BigQuery or Analytics-linked notification interaction events | Firebase project owner. No Analytics dependency was found in `pubspec.yaml`, but console settings must still be checked. |
89+
| Play Console submission | Play Console owner. |
90+
91+
## Pre-Submission Checklist
92+
93+
1. Confirm the release build's exact dependency set and SDK configuration.
94+
2. Re-run the source audit after final release branch changes.
95+
3. Confirm backend deletion and retention behavior for normal, Google, and Apple
96+
account paths.
97+
4. Approve the privacy policy and verify every declared data type appears in it.
98+
5. Verify the public privacy policy URL works without login and is the same URL
99+
used in app and Play Console.
100+
6. Verify the public account deletion URL works without installing or opening
101+
the app and explains deleted and retained data.
102+
7. Enter the Data safety form in Play Console from this worksheet plus approved
103+
owner answers.
104+
8. Save the final submitted answers back into release documentation, replacing
105+
or appending to this worksheet.
106+
107+
## Suggested Final Documentation Template
108+
109+
After Play Console submission, append a section named `Submitted Answers` with:
110+
111+
- Submission date and Play Console owner.
112+
- Privacy policy URL.
113+
- Account deletion URL.
114+
- Data types declared as collected.
115+
- Data types declared as shared, if any.
116+
- Purpose, required/optional status, and deletion support for each data type.
117+
- Encryption in transit answer.
118+
- Any retained data exceptions and retention period.
119+
- Evidence screenshots or links stored outside git, if applicable.

0 commit comments

Comments
 (0)