diff --git a/android/PLAN.md b/android/PLAN.md index e59689e..3247618 100644 --- a/android/PLAN.md +++ b/android/PLAN.md @@ -85,7 +85,7 @@ change/set password (the SSO-account "no current password" path from `has_passwo list/unlink SSO identities — each mutation folding its `ApiResult` into a section-scoped, localized banner (§7). **Game-account linking** (§6.3) — the in-game `[link` one-time code (`POST /player/shard/link`) plus the hybrid signup (`POST /player/shard/account`, shown only when the public -`gameAccountSignup` flag is set), and the linked-accounts list. **Own game data**, text-only (§6.3): +`gameAccountSignup` flag is set — see the OWED note below), and the linked-accounts list. **Own game data**, text-only (§6.3): per-account character roster → a character sheet (attributes, vitals, resistances, best-first skills, equipment with AOS mods, and guild/governor standing chips — bare cliloc-number titles/item names are skipped, as the app ships no cliloc table, matching the website's `CharacterSheet.jsx`); player @@ -99,6 +99,18 @@ spec-aligned (as recorded for M1); 17 new JVM unit tests cover the account + pla **No backend/API change** — the `/auth/me/*` and `/player/shard/*` surfaces the app consumes were the §8 prerequisites, already landed. +> **OWED — `gameAccountSignup` moved and the app has not followed (2026-08-11).** Phase 3 slice 3 of +> the website's module extraction (`docs/website/MODULE_SYSTEM.md` §2.7.1) moved game-account signup +> policy out of core: the flag is no longer on `GET /public/settings` and is now on module-uo's +> `GET /public/shard/features`, beside the visibility flags. `PublicDto.kt:80` defaults it to +> `false`, so **nothing crashes** — `CharactersViewModel.kt:72` reads `false` and the app simply +> stops offering game-account creation. The fix is one DTO field, one ViewModel line and two tests, +> reading the flag from the features endpoint the app already calls. +> +> Deferred rather than coordinated into the slice (org lead, 2026-08-11): the website work lands on +> `edge` and reaches `main` as one cutover, so there is room. **It must land before that cutover** — +> after it, a shipped app quietly loses a feature. + ✅ **M5 — design pass** (2026-07-20, `RunicGateway/Android-app#10`): the shard-website theme applied across every screen, restyling the working M1–M4 UI with **no architecture, data-flow, endpoint, or DTO change** (§2.1). The design was produced in Claude Design (`Runic Gateway Screens.dc.html`) and diff --git a/website/BACKEND_DESIGN.md b/website/BACKEND_DESIGN.md index 032ab13..2f0726d 100644 --- a/website/BACKEND_DESIGN.md +++ b/website/BACKEND_DESIGN.md @@ -908,7 +908,7 @@ from the per-route **siteMode** middleware (§5), never from an auth gate. | Method | Path | Notes | |---|---|---| -| GET | `/settings` | whitelisted public keys, derived `registration`/`gameAccountSignup` flags, the per-shard **`brand`** block (name, `accent` color, logo/hero/favicon) a client themes itself from — one image runs as any shard, asset fields may be site-relative paths (resolve against the base URL); these are **effective** values, so an admin theme (`theme_visual`) beats `BRAND_ACCENT_COLOR` and an uploaded `brand_assets` asset beats its `BRAND_*` path — an optional **`theme`** block, the resolved CSS custom properties for that admin theme (absent when the instance was never themed, which is what makes it render from the shipped stylesheet unchanged) — and a **`push`** block `{ ntfyUrl }` (M7): the client-facing ntfy relay URL the app's embedded distributor registers its device topic against, from `NTFY_PUBLIC_URL` / first `NTFY_ALLOWED_ORIGINS` (never the internal `NTFY_BASE_URL`); `null` when push isn't configured for the shard. | +| GET | `/settings` | whitelisted public keys, the derived `registration` flags (`gameAccountSignup` was one of these until the module extraction moved game-account policy to module-uo — it is on that module's `GET /public/shard/features` now, and the `game_account_signup` settings row is unchanged), the per-shard **`brand`** block (name, `accent` color, logo/hero/favicon) a client themes itself from — one image runs as any shard, asset fields may be site-relative paths (resolve against the base URL); these are **effective** values, so an admin theme (`theme_visual`) beats `BRAND_ACCENT_COLOR` and an uploaded `brand_assets` asset beats its `BRAND_*` path — an optional **`theme`** block, the resolved CSS custom properties for that admin theme (absent when the instance was never themed, which is what makes it render from the shipped stylesheet unchanged) — and a **`push`** block `{ ntfyUrl }` (M7): the client-facing ntfy relay URL the app's embedded distributor registers its device topic against, from `NTFY_PUBLIC_URL` / first `NTFY_ALLOWED_ORIGINS` (never the internal `NTFY_BASE_URL`); `null` when push isn't configured for the shard. | | GET | `/status` | status message + current mode, **plus a `version` block** (`{ service:'runic-gateway', api, server }`) so a client first-run probe recognizes the backend and can run a version-mismatch guard | | GET | `/version` | lightweight, **DB-free** backend identity/version (`{ service, api, server }`) — the canonical target for the version guard and a cheap liveness check | | GET | `/modules` | `{ modules: [{ id, name, version, capabilities }] }` — the modules this backend is currently **serving**, in scan order (module system, `MODULE_API.md` §2.9). A module that is disabled or failed to load is **absent**, not listed with a state: its routes and nav are absent too, so the client renders a site without that capability rather than advertising one that 503s. The recorded failure stage and reason are admin-panel detail and are never published here. `capabilities` are opaque strings the module declares — feature-detect against them and treat an unknown one as absent. Like `/status` and `/version` it is **DB-free and not site-mode gated**, so a client can still feature-detect during maintenance. It is *not* how a module's client chunk loads — `htmlShell` injects a `