diff --git a/ANDROID_PLAN.md b/ANDROID_PLAN.md index a4ec135..fc7223b 100644 --- a/ANDROID_PLAN.md +++ b/ANDROID_PLAN.md @@ -62,6 +62,76 @@ client-only (no server change). Kept current as parts land so a fresh session resumes without re-deriving. Verify against code. +> ### ▶ RESUME HERE — 2026-07-13 (documents track + release-prep) +> +> **Where we are.** The legal-documents track and the release-prep hygiene are DONE. The RuStore +> release is now gated on **owner-side** items (icon vector, keystore, RuStore account). The owner is +> bringing the **icon vector** next; **when it lands, resume by generating the icon set** per +> [`docs/ICONS.md`](docs/ICONS.md), then continue the release chain below. Do not re-do or re-litigate +> the finished work; do not re-ask the locked decisions. +> +> **Branches / PRs (current working branch: `feature/android-release-prep`).** +> - `development` — has the **legal-documents track**, merged via **PR #253** (green, deployed to the +> test contour). `/privacy/`, `/eula/`, `/offer/` are live there, bilingual RU/EN. +> - `feature/android-release-prep` — the **release-prep hygiene**, **PR #254 OPEN, green, NOT merged** +> (the owner chose to hold the merge). It is branched off `development`, so it also contains the +> legal-documents track. Merge #254 into `development` when ready — needs **owner approval** (the +> agent cannot self-approve). +> +> **Done this session.** +> - **Legal documents** (satisfies the RuStore *hosted privacy-policy URL* prerequisite): authored +> `ui/legal/{privacy,eula,offer}_{ru,en}.md`; served as **bilingual (RU/EN)** standalone pages by the +> render sidecar at `/privacy/`, `/eula/`, `/offer/` via the shared `ui/src/lib/offer.ts` +> `renderLegalHtml`, with a client-side **language + theme switcher** (🌐 + ☼/☾, no "back", default +> Russian + persisted, mirroring the landing). The offer's EN view **transliterates** the Russian +> product names and **translates** the price-list section headings + column headers (`PRICE_TR`). +> Edge: `@legal` caddy matcher (`/offer/ /privacy/ /eula/`) + CI probes (size-independent head-only +> for the legal pages, retry for the offer). Landing footer links: Пользовательское соглашение | +> Политика конфиденциальности | Публичная оферта | Обратная связь (→ the Telegram bot). Docs baked +> into `docs/ARCHITECTURE.md`, `docs/FUNCTIONAL.md` (+`_ru`), `renderer/README.md`. +> **Locked legal decisions — do NOT re-litigate:** seller **INN `290210610742`**; EULA §14 leads +> with **RF law + jurisdiction** as residence tiers (France / England&Wales retained as foreign +> tiers); the "only the English version is legally binding" clause is **removed**; data collection is +> kept but **scoped to voluntary/support provision** (passport/payment/ID only when the user provides +> them); «Компания» is not shout-cased; the offer's EN catalog product names are **transliterated** +> (owner-chosen), while its headings/columns are translated. +> - **Release-prep hygiene (PR #254):** de-anchored `ANDROID_PLAN.md` from all code/docs — **no +> reference to this file remains anywhere outside it**; **re-enabled the `android-build` workflow** +> (`.gitea/workflows/android-build.yaml.disabled` → `.yaml`; it is `workflow_dispatch`-only + gated +> `if master`, so it never auto-runs; the CI host already has the Android SDK at `/opt/android-sdk`); +> added [`docs/ICONS.md`](docs/ICONS.md) (the single-master icon/logo format reference). +> +> **Remaining to release (owner-gated unless the agent is named).** +> 1. **Icon rebrand.** OWNER brings a final **vector (SVG)** master (+ optional format guides). AGENT +> then generates every target per `docs/ICONS.md`. Obligatory source files: the vector + a +> **1024×1024 opaque PNG**; recommended: `ui/assets/icon-foreground.png` + `icon-background.png` for +> a proper Android/iOS adaptive icon. Today the web favicon generator (`assets/icons/`) and the +> hand-placed PWA icons drift — unify onto the new master. **Open sub-decision (settle with the owner +> when the vector arrives):** retarget the `assets/icons/` generator onto the new vector, or drop in +> the output files and keep the generator for the OG card only. +> 2. **Merge PR #254** → `development` (owner approval), then **promote `development` → `master`** and +> **tag `vX.Y.Z`** for the release (the version stamps the APK `versionName`/`versionCode` and the +> `X-Client-Version` header). +> 3. **Release keystore.** OWNER generates it (`keytool -genkeypair -v -keystore erudit-release.jks +> -alias erudit -keyalg RSA -keysize 4096 -validity 10000`), base64-encodes it, sets the four Gitea +> **secrets** `ANDROID_KEYSTORE_BASE64` / `ANDROID_KEYSTORE_PASSWORD` / `ANDROID_KEY_ALIAS` / +> `ANDROID_KEY_PASSWORD`, and backs the `.jks` up **off-host** (loss ⇒ the app can never be updated). +> The AGENT provides the exact commands on request. Without the secrets the workflow builds an +> UNSIGNED APK (a dry run still proves the pipeline). +> 4. **RuStore developer account.** OWNER (verified legal entity or self-employed / самозанятый). Gates +> publication, not the build. +> 5. **Dispatch the signed build.** AGENT: on `master`, dispatch `android-build` (`confirm=build`) via +> `tea`, watch to green, retrieve the signed APK artifact (verify Gitea 1.26 `upload-artifact@v4` at +> the dispatch). +> 6. **On-device smoke.** OWNER installs the signed APK and runs the airplane-mode first-launch +> checklist (`docs/TESTING.md`). The AGENT can pre-run the emulator smoke. +> 7. **Store listing.** Reserve `ru.eruditgame.app`, title «Эрудит», RU description, phone screenshots, +> icon / feature graphic, age rating, the **privacy-policy URL `https://erudit-game.ru/privacy/`** +> (now available), the content declaration. +> 8. **Upload to RuStore.** OWNER. After publication, set the `ANDROID_RUSTORE_URL` Gitea variable to +> the store deep-link so the update button works on future gated releases (empty until then — the +> gate is dormant in the MVP). + - **A. Capacitor scaffolding — ✅ DONE & verified (2026-07-12).** Capacitor 8 native project generated under `ui/android/` (tracked), `@capacitor/*` deps + `capacitor.config.ts`, hardware Back in `ui/src/lib/native.ts` wired from `App.svelte`. `pnpm build` → `cap sync` → `./gradlew assembleDebug` @@ -695,6 +765,13 @@ Wire in `ui/android/app/build.gradle` `defaultConfig`: ### G. Release + owner handoff +> **Status 2026-07-13 — see the ▶ RESUME block at the top of §Progress.** Since this chain was +> written, a **legal-documents track** was added and merged (PR #253 — the RuStore hosted +> privacy-policy URL and the `/privacy/ /eula/ /offer/` pages), and a **release-prep hygiene** patch is +> in flight (PR #254, open). The remaining gates are the **icon vector**, the **keystore** and the +> **RuStore account** (all owner-side). The steps below are the original release chain; the resume +> block supersedes them with the current, exhaustive state. + 0. **Land the offline-model redesign — ✅ DONE (O1–O7, 2026-07-13; staged detail below).** Resolved the deferred native local-game-visibility decision — a native guest now sees / resumes their device-local games once online (the **unified lobby**, O5) — as part of the owner-approved change: the explicit offline toggle is gone, offline