diff --git a/android/PLAN.md b/android/PLAN.md index 8f02705..e66dc84 100644 --- a/android/PLAN.md +++ b/android/PLAN.md @@ -923,6 +923,71 @@ push, and Play (M6–M8) follow the designed app. its `NTFY_*` deploy config (§13). 9. **M8 — Google Play**: Play Console listing, signing/upload key, and (optionally) an FCM build flavor — after the direct-APK release is stable. + + **Planned 2026-10-23**, after v0.6.0. The direct APK stays the default channel (§10); Play is + added beside it, not instead of it. + + **Where the console stands (read 2026-10-23).** The app `com.runicgateway.app` exists as a + draft on a **personal** developer account. 7 of 11 setup tasks are done: privacy policy + (runicgateway.com `/privacy/`), ads (none), content rating, government, financial, health, and + category + contact. Still open: sign-in details, target audience, data safety (started), the + advertising ID declaration, and the store listing. No build has been uploaded yet. + + **Decisions (org lead, 2026-10-23):** + - **Signing: reuse the existing release keystore as Play's app-signing key.** It is uploaded at + the first release with Play's "use my own key" option, through Google's encrypted export + tool. So a Play install and a sideloaded APK from Gitea have the same signature, and a user + can move between them without uninstalling. This cannot be changed after the first upload. + - **CI publishes every `v*` tag to the internal track.** Promotion to closed testing, and later + to production, is a click in the console, so a tag never reaches testers or review on its + own. + - **The review and beta site is `demo.runicgateway.com`**, a dedicated Runic Gateway deployment + on the Oxide Rust rig. Google's reviewers and the closed-test testers sign in there. It is + runicgateway.com's D27 demo, given a host. The website changes it needs (demo accounts, a + lock on breaking settings, a periodic wipe) are their own feature: `RunicGateway/website#222`. + + **What Play requires that the app does not do today:** + - **Target API 36.** Since 2026-08-31, new apps and updates must target Android 16 (API 36). + The app targets 35. That means `compileSdk`/`targetSdk` 36, an AGP bump (8.6.1 does not + support 36), the SDK packages in both workflows, and a check of Android 16's behaviour + changes on a device. + - **An app bundle.** Play takes an AAB, not an APK. `release.yml` keeps building the signed + APK for the Gitea release and adds `bundleRelease`, signed with the same keystore. + - **The upload.** After the Gitea release, a step in `release.yml` uploads the AAB to the + internal track through the Google Play Developer API (`edits` → bundle upload → track → + commit). It authenticates with a service-account key in a new secret, + `PLAY_SERVICE_ACCOUNT_JSON`, the account having release rights on this app only. The step + uses `curl` + `jq` + `openssl` (for the JWT), in the style of the existing Gitea release step, + and adds no Gradle plugin. Gradle Play Publisher is the alternative if the script proves + brittle. **Google requires the first bundle to be uploaded by hand in the console**; CI owns + every upload after it. A Play failure fails the run *after* the Gitea release exists, so + the APK channel never waits on Google. + + **Order of work:** + 1. **App + CI** (one PR into `edge`): API 36 + AGP bump, AAB, Play upload step. Walked on the + emulator and the S22 before the PR. + 2. **First bundle**, uploaded by hand from the next tag, with the signing key enrolled. + 3. **Console declarations**: target audience 18+ (runicgateway.com D31), advertising ID none, + data safety from runicgateway.com's generated `PLAY_DATA_SAFETY.md`, and sign-in details + pointing at `demo.runicgateway.com` with a reviewer account. Then the store listing. + 4. **Closed test**, once the demo site is up: a personal account needs **12 testers opted in + for 14 days in a row** before it can apply for production. runicgateway.com `/beta` + collects them. + + **Open, each waiting for a decision:** + - **Content rating.** The questionnaire answered "Social or Communication: moderated chat; + users or user-generated content can be reported". The app shows other players' chat (the + Rust feed) but has no report or block action, and Play's user-generated-content policy + expects both where that is declared. Either retake the questionnaire, or add report/block + to the app. + - **Data safety's premise.** The generated notes answer "not collected" almost everywhere, + because the app talks only to a deployment the user chose. The notes call it the answer + most likely to be questioned in review. Declaring user IDs and messages as collected, + encrypted in transit and needed for the app to work, is the conservative alternative. + - **The push foreground service.** Play asks for a declaration (and a video) for the + `dataSync` service that holds the ntfy connection. Google reserves `dataSync` for transfers, + and Android 15 limits it to six hours a day. This brings forward §13's "FCM flavor for + Play?" question. 10. **M9 — Native SSO login** (post-v1, additive; independent of M8): in-app "Sign in with Google / Discord" via the **Mobile SSO Authorization Bridge** (§4.2). **Backend-first**, mirroring M7's split: