Merge pull request 'docs(safety): record USER_SAFETY step 4, the app's chat-line menu' (#401) from docs/user-safety-android into main

Reviewed-on: #401
This commit is contained in:
2026-10-30 15:29:56 +00:00
2 changed files with 38 additions and 8 deletions

View File

@@ -1062,7 +1062,8 @@ push, and Play (M6–M8) follow the designed app.
and it takes `MODULE_API` 1.20.0 (org lead, 2026-10-29). The app's part, the *Delete my and it takes `MODULE_API` 1.20.0 (org lead, 2026-10-29). The app's part, the *Delete my
account* screen reached from *My account*, was built 2026-10-30 (that plan's §6 step 4). account* screen reached from *My account*, was built 2026-10-30 (that plan's §6 step 4).
4. **Report, block and hide** across `website`, `Module-Rust`, the kit and this app 4. **Report, block and hide** across `website`, `Module-Rust`, the kit and this app
(`USER_SAFETY.md` §7), now `MODULE_API` 1.21.0. (`USER_SAFETY.md` §7), now `MODULE_API` 1.21.0. The app's part, a long-press menu on Rust
chat lines and *Account → Blocked*, was built 2026-10-30 (that plan's §7 step 4).
5. **The cutover**, `edge` → `main`, once 1-4 have landed, so the first Play bundle carries 5. **The cutover**, `edge` → `main`, once 1-4 have landed, so the first Play bundle carries
all of it. **Before it merges, the org lead enrolls the existing keystore as the app-signing all of it. **Before it merges, the org lead enrolls the existing keystore as the app-signing
key** in Play Console (App integrity, "use my own key"). `PLAY_SERVICE_ACCOUNT_JSON` is key** in Play Console (App integrity, "use my own key"). `PLAY_SERVICE_ACCOUNT_JSON` is

View File

@@ -1,7 +1,7 @@
# Report, block and hide — user safety on the website and in the app # Report, block and hide — user safety on the website and in the app
**Status:** plan of record, 2026-10-29. Steps 2 (core) and 3 (Module-Rust, Integration Kit) built **Status:** plan of record, 2026-10-29. Steps 2 (core), 3 (Module-Rust, Integration Kit) and 4
2026-10-30 (§7); the rest not yet. (Android) built 2026-10-30 (§7); the rest not yet.
Each phase stops for the org lead before the next one starts. Built after account deletion Each phase stops for the org lead before the next one starts. Built after account deletion
([`ACCOUNT_DELETION.md`](ACCOUNT_DELETION.md)), which is why it is `MODULE_API` 1.21.0. §4 was ([`ACCOUNT_DELETION.md`](ACCOUNT_DELETION.md)), which is why it is `MODULE_API` 1.21.0. §4 was
amended by S11-S14 (§5) when the core was built. amended by S11-S14 (§5) when the core was built.
@@ -148,11 +148,22 @@ All of it is in `server/safety.js`, beside the events route that uses it.
### 4.3 Android app (chat lines only, S4) ### 4.3 Android app (chat lines only, S4)
- **Long-press a chat line** for the same menu. Report opens a sheet with the six reasons and an - **Long-press a chat line** for the same menu, in a bottom sheet: *Report* (the six reasons and
optional detail. A member who is signed out gets *Sign in to report or block*. an optional detail), *Hide for me*, *Block player* (where the line says `canBlock`, after a
- **Account → Blocked** lists blocks and undoes them, mirroring the web page. confirmation that says the player is not told) and, for admins and moderators, *Hide for
- The feed is already filtered by the server (S11); the app refetches after a block or a hide and everyone* or, on a hidden line, *Show to everyone again*. Only chat lines answer the press. A
offers *Block player* only where the line says `canBlock`. member who is signed out gets *Sign in to report or block*, which opens the app's login screen.
Back on the report form or the block confirmation returns to the menu, keeping what was typed.
- The calls are core's (`/player/reports`, `/auth/me/blocks`, `/auth/me/hidden`) and the
module's two staff routes. Each refusal has its own sentence: already reported or blocked,
gone, staff (S8), too many reports, the module not answering, the demo's lock.
- The feed is already filtered by the server (S11); the app reads it again after a hide, a block
or a staff hide, and never drops a line itself. A report changes nothing, so it does not. Staff
see a line hidden for everyone dimmed and marked *Hidden by staff* (S10).
- **Account → Blocked** (from *My account*) lists blocks with *Unblock*, mirroring the web page:
an account block by its username, a Steam-ID block by its ID and "not linked to an account", and
a block whose target is now staff with *Not applied* and why (S8). *Show them again* clears the
member's hides.
## 5. Further decisions (org lead, 2026-10-29) ## 5. Further decisions (org lead, 2026-10-29)
@@ -224,6 +235,24 @@ Play declarations gain "user-generated content: collected". M21 says so.
a moderator *Hide for everyone* / *Show to everyone again* with the *Hidden by staff* marker and a moderator *Hide for everyone* / *Show to everyone again* with the *Hidden by staff* marker and
the Reports queue showing both chat-line reports from their snapshots. No console errors. the Reports queue showing both chat-line reports from their snapshots. No console errors.
4. **Android** (`edge`): §4.3. One PR. 4. **Android** (`edge`): §4.3. One PR.
**Built 2026-10-30** as Android-app `feat/user-safety`. `./gradlew testDebugUnitTest lintDebug
assembleDebug` green: 827 tests, 29 of them new (the menu's rules, the repository's refusals,
both view models), and no lint findings in the new code. Walked on the `Medium_Phone_API_36.1`
emulator against a core on its own port with Module-Rust installed and a throwaway database,
chat lines and Steam links written into the tables: signed out, a long press offered only
*Sign in*, which opened the login screen; as a member, a report reached `content_reports`
with its reason, detail and snapshot, and a second one was refused as already reported; *Hide
for me* took one line out; blocking an unlinked speaker made a Steam-ID block and took their
chat (not their death) out; blocking a linked speaker made an account block; the moderator's
line and the member's own offered no *Block*, and a death offered no menu. *Account →
Blocked* listed both; linking the Steam ID turned that block into an account block (S14);
making that account a moderator showed *Not applied* (S8); *Unblock* and *Show them again*
brought the lines back. As a moderator, *Hide for everyone* dimmed and marked the line for
staff, took it out of a signed-out read and wrote `rust.chat.hide` to the activity log, and
*Show to everyone again* undid it. The walk found two things, both fixed: Back to put the
keyboard away closed the whole sheet and lost a half-written report, and the half-open sheet
left *Send report* below the fold.
5. **A walk** on the demo after the next wipe: report, hide and block, each on the web and in the 5. **A walk** on the demo after the next wipe: report, hide and block, each on the web and in the
app; *Hide for everyone* from the queue; a blocked Steam ID that later links to an account stays app; *Hide for everyone* from the queue; a blocked Steam ID that later links to an account stays
blocked. blocked.