Compare commits
10 Commits
caab3476eb
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| f38dec2ac4 | |||
| 080f9827b8 | |||
| 7ac19a791c | |||
| b8306dcdaf | |||
| 08a4973bde | |||
| 8b8896f54b | |||
| e5ec81b172 | |||
| e0b2885cd7 | |||
| c1b38081f5 | |||
| dff4232491 |
@@ -157,6 +157,21 @@ jobs:
|
||||
docker push "${IMAGE}:latest"
|
||||
docker push "${IMAGE}:${TAG}"
|
||||
|
||||
- name: Remove this run's image and cap the build cache
|
||||
# The build runs on the HOST daemon, so whatever it leaves stays on the
|
||||
# runner host for good: every run used to leave two tagged images, and
|
||||
# each newer `latest` turned the previous one into a permanent `sha-` image
|
||||
# until the host ran out of disk. Both tags are in the registry by now, so
|
||||
# the local copies are dead weight. BuildKit keeps its layer cache apart
|
||||
# from the images, so the next build stays fast; the cache is pruned to a
|
||||
# cap instead of growing forever (`--reserved-space` is the same flag's
|
||||
# name on newer Docker). Runs even after a failure, and never fails the job.
|
||||
if: always()
|
||||
run: |
|
||||
docker image rm "${IMAGE}:latest" "${IMAGE}:${TAG}" 2>/dev/null || true
|
||||
docker builder prune -f --keep-storage 5GB \
|
||||
|| docker builder prune -f --reserved-space 5GB || true
|
||||
|
||||
- name: Log out
|
||||
if: always()
|
||||
run: docker logout "${REGISTRY}" || true
|
||||
@@ -207,3 +222,11 @@ jobs:
|
||||
echo "::error::The site did not become healthy within 150s."
|
||||
docker compose logs --tail 100 site
|
||||
exit 1
|
||||
|
||||
- name: Remove the image this deploy replaced
|
||||
# The pull moves `latest` to the new image and leaves the old one untagged
|
||||
# on the host. Untagged images are never used again (a rollback pulls a
|
||||
# `sha-` tag from the registry), so drop them. Dangling images only: nothing
|
||||
# tagged and nothing a container is using is touched.
|
||||
if: always()
|
||||
run: docker image prune -f || true
|
||||
|
||||
2
PLAN.md
2
PLAN.md
@@ -956,6 +956,8 @@ deliberately so — no fetch can tell whether an APK runs. `checkFacts.mjs` asse
|
||||
still exist and that `minSdk` still says what "Android 10 or newer" claims, so the link is correct
|
||||
the moment a working build flips the boolean. The panel is not removed while the link is off: a page
|
||||
that omitted sideloading would read, to somebody who knows the APK exists, as a page hiding it.
|
||||
*(2026-10-31: the link is back on. Android `v0.7.0`'s APK was installed on an Android 16 emulator,
|
||||
connected to the public demo and read its Rust servers, so `serviceable` is `true`.)*
|
||||
|
||||
**Three mechanisms this phase added that the plan did not anticipate.**
|
||||
|
||||
|
||||
@@ -38,7 +38,8 @@ Play still counts what the app sends to that server as **collected**: the data l
|
||||
| Messages | Other in-app messages | Yes | No | Yes | App functionality | Your name, email address and message, if you use Contact; What you post and send from the app |
|
||||
| App activity | App interactions | Yes | No | Yes | App functionality; Personalization | Which notifications you have read, and which you want |
|
||||
| App activity | In-app search history | Yes | No | Yes | App functionality | What you search for |
|
||||
| App activity | Other user-generated content | Yes | No | Yes | App functionality | What you post and send from the app |
|
||||
| App activity | Other user-generated content | Yes | No | Yes | App functionality; Fraud prevention, security, and compliance; Personalization | What you post and send from the app; What you report, block or hide |
|
||||
| App activity | Other actions | Yes | No | Yes | App functionality; Fraud prevention, security, and compliance; Personalization | What you report, block or hide |
|
||||
| App info and performance | Diagnostics | Yes | No | Yes | App functionality; Fraud prevention, security, and compliance | The app’s version and your Android version |
|
||||
| Device or other IDs | Device or other IDs | Yes | No | Yes | App functionality; Fraud prevention, security, and compliance; Account management | The trusted-device token and the device’s name, if you asked for one; Push registration, if you turn notifications on |
|
||||
|
||||
@@ -56,7 +57,7 @@ The form lists every type, so every one is answered. Vocabulary read from Play C
|
||||
- **Files and docs:** none collected.
|
||||
- **Calendar:** none collected.
|
||||
- **Contacts:** none collected.
|
||||
- **App activity:** Installed apps, Other actions: not collected.
|
||||
- **App activity:** Installed apps: not collected.
|
||||
- **Web browsing:** none collected.
|
||||
- **App info and performance:** Crash logs, Other app performance data: not collected.
|
||||
|
||||
@@ -169,6 +170,19 @@ Most of the app is reading. What it sends is what you write, and most of that is
|
||||
- **Retention:** Held by the deployment, under its operator’s policy
|
||||
- **Read from:** `data/api/AdminApi.kt`
|
||||
|
||||
### What you report, block or hide
|
||||
|
||||
**App activity → Other user-generated content; App activity → Other actions.** Collected, not shared, required.
|
||||
|
||||
Purposes: App functionality; Fraud prevention, security, and compliance; Personalization.
|
||||
|
||||
Long-pressing a chat line offers Report, Hide for me and Block player. A report sends which line it is, the reason you picked and, if you wrote one, a note of up to 500 characters, so the deployment’s staff can review it. Hide for me and Block player send which line it is; the deployment works out who wrote it and keeps the hide or the block on your account, so it applies on the website and on every device. Your list of blocks, and unblocking someone, come from and go to the same place. For staff, Hide for everyone and Show to everyone again send the line too. Nothing is sent until you choose one.
|
||||
|
||||
- **Why that answer:** The report’s note is text the user writes, and reporting, blocking and hiding are actions the app sends to the deployment, which keeps them. Reports exist so staff can act on abuse; blocks and hides change what this one reader is shown.
|
||||
- **Retention:** Held by the deployment, under its operator’s policy
|
||||
- **In detail:** A block or a hide lasts until you remove it or delete the account, which deletes them. A report stays as a moderation record, with a copy of what the line said, until the operator removes it.
|
||||
- **Read from:** `data/api/SafetyApi.kt, data/api/dto/SafetyDto.kt, data/api/RustApi.kt`
|
||||
|
||||
### Which notifications you have read, and which you want
|
||||
|
||||
**App activity → App interactions.** Collected, not shared, required.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: Moderation
|
||||
description: Three screens that do three different jobs — Discord moderation, content reports, and appeals against a sanction.
|
||||
description: Three screens that do three different jobs — Discord moderation, content reports, and appeals against a sanction — and what members can do for themselves.
|
||||
---
|
||||
|
||||
import { Aside } from '@astrojs/starlight/components';
|
||||
@@ -11,7 +11,7 @@ not overlap.
|
||||
| Screen | Is about | Comes from |
|
||||
|---|---|---|
|
||||
| **Moderation** | Your **Discord** server — bans, kicks, mutes, warnings, joins, leaves, filter and spam hits | the bot, captured live |
|
||||
| **Reports** | **Team forum content** members have reported | the site |
|
||||
| **Reports** | **Content** members have reported — Team forum threads and posts, and a game's chat lines where its module offers them | the site |
|
||||
| **Appeals** | Sanctions people are asking you to reverse | the site |
|
||||
|
||||
## Moderation (Discord)
|
||||
@@ -29,13 +29,20 @@ browsing the window.
|
||||
|
||||
## Reports
|
||||
|
||||
Reports raised by members about Team forum content. Two design decisions show through in
|
||||
how this screen behaves:
|
||||
Reports raised by members about Team forum threads and posts and, where a game module offers
|
||||
it, the game's chat lines — the Rust module does, from the `⋯` menu on a chat line on the
|
||||
site and a long press in the [app](/app/). Each report keeps a copy of what the item said when it was
|
||||
reported, so an author editing it afterwards does not change what staff read. Three design
|
||||
decisions show through in how this screen behaves:
|
||||
|
||||
- **They come to site staff, and a Team's own leaders never see them.** A leader moderates
|
||||
their own forum, so a report *about a leader* has to reach someone above them.
|
||||
- **Handling a report records a decision about the report.** It does not touch the content:
|
||||
hiding or removing a post is done in the forum, or as a sanction against the account.
|
||||
- **A report changes nothing on its own.** Filing one must never be a way to hide
|
||||
something, so the reported item stays where it is until staff act.
|
||||
- **Acting is a separate, deliberate step.** *Hide for everyone* on a report hides the item
|
||||
from everybody except staff, who still see it marked *Hidden by staff* and can show it
|
||||
again, and it records the report as actioned. Removing content outright, or sanctioning the
|
||||
account, is still done in the forum or against the account.
|
||||
|
||||
The filters are *Open*, *Reviewing*, *Actioned*, *Dismissed* and *All*, and the count of
|
||||
open reports sits at the top so the screen is glanceable.
|
||||
@@ -46,6 +53,19 @@ that never empties stops being read, and the reporter's next report is the one t
|
||||
matters.
|
||||
</Aside>
|
||||
|
||||
## What members do for themselves
|
||||
|
||||
Two tools need no staff at all, and nothing about them reaches the queue:
|
||||
|
||||
- **Hide for me** takes one item out of that member's own view, on every device.
|
||||
- **Block** takes everything a person writes — chat lines and forum content — out of the
|
||||
blocker's view, on the site and in the app. The blocked person is not told. Staff cannot be
|
||||
blocked, and a block whose target later becomes staff stops applying and says so. A game
|
||||
player who has not linked a site account is blocked by their game identity, which turns
|
||||
into a block on their account if they link one later.
|
||||
|
||||
A member undoes either from **Account → Blocked**.
|
||||
|
||||
## Appeals
|
||||
|
||||
An appeal is a request to reverse a sanction, filtered by *Open*, *Pending*, *Under
|
||||
|
||||
@@ -42,7 +42,7 @@ with six tabs.
|
||||
|
||||
| Tab | What it shows |
|
||||
|---|---|
|
||||
| **Feed** | Kills, chat, comings and goings, the server's own story, RunicNPC bosses, and Rust's world events — cargo, helicopters, airdrops — as they happen |
|
||||
| **Feed** | Kills, chat, comings and goings, the server's own story, RunicNPC bosses, and Rust's world events — cargo, helicopters, airdrops — as they happen. A signed-in member can report a chat line, hide it for themself or block the player from its `⋯` menu, and staff can hide a line for everyone ([Moderation](/docs/administration/moderation/)) |
|
||||
| **Leaderboard** | Per wipe: kills, deaths, NPC kills, structures, time played, and the chat titles players have earned |
|
||||
| **Online** | Who is on right now |
|
||||
| **Map** | The [live map](/docs/rust/the-live-map/): the server's own map picture, with layers |
|
||||
|
||||
@@ -128,6 +128,22 @@ export const appFeatures = [
|
||||
'Visible to the account they belong to and to nobody else.',
|
||||
gate: 'A game module',
|
||||
},
|
||||
{
|
||||
title: 'Report, block and hide',
|
||||
body:
|
||||
'Long-press a chat line to report it to the site’s staff, hide it for yourself, or ' +
|
||||
'block the player. A block is kept on your account, so it applies on the website and ' +
|
||||
'on every device too; staff cannot be blocked, and Account → Blocked undoes any of ' +
|
||||
'it. Staff get Hide for everyone on the same menu.',
|
||||
gate: 'A game module whose chat lines can be reported (Rust)',
|
||||
},
|
||||
{
|
||||
title: 'Deleting your account',
|
||||
body:
|
||||
'From My account, with your password and, where the account has one, a two-factor ' +
|
||||
'code. The account is deleted on the deployment at once — see what that removes and ' +
|
||||
'what it keeps on the delete-account page.',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -499,6 +499,51 @@ export const collected = [
|
||||
'We have no copy, no access and no way to obtain one.',
|
||||
},
|
||||
},
|
||||
/*
|
||||
* Report, block and hide (USER_SAFETY.md §4.3), on Android-app#64 rather than the edge
|
||||
* commit the section header names. Read out of `data/api/SafetyApi.kt` and
|
||||
* `data/api/dto/SafetyDto.kt`: a report sends the item's type and id, a reason and an
|
||||
* optional note; a block and a hide send the item's type and id; unblocking sends the
|
||||
* block's id. No request names the person being blocked — the deployment works out who
|
||||
* wrote the line — so none of it is a User ID.
|
||||
*/
|
||||
{
|
||||
id: 'app-safety',
|
||||
scope: 'app',
|
||||
title: 'What you report, block or hide',
|
||||
body:
|
||||
'Long-pressing a chat line offers Report, Hide for me and Block player. A report ' +
|
||||
'sends which line it is, the reason you picked and, if you wrote one, a note of up to ' +
|
||||
'500 characters, so the deployment’s staff can review it. Hide for me and Block ' +
|
||||
'player send which line it is; the deployment works out who wrote it and keeps the ' +
|
||||
'hide or the block on your account, so it applies on the website and on every device. ' +
|
||||
'Your list of blocks, and unblocking someone, come from and go to the same place. For ' +
|
||||
'staff, Hide for everyone and Show to everyone again send the line too. Nothing is ' +
|
||||
'sent until you choose one.',
|
||||
retention: {
|
||||
summary: 'Held by the deployment, under its operator’s policy',
|
||||
detail:
|
||||
'A block or a hide lasts until you remove it or delete the account, which deletes ' +
|
||||
'them. A report stays as a moderation record, with a copy of what the line said, ' +
|
||||
'until the operator removes it.',
|
||||
},
|
||||
source: 'data/api/SafetyApi.kt, data/api/dto/SafetyDto.kt, data/api/RustApi.kt',
|
||||
play: {
|
||||
types: [
|
||||
{ category: 'App activity', type: 'Other user-generated content' },
|
||||
{ category: 'App activity', type: 'Other actions' },
|
||||
],
|
||||
collected: true,
|
||||
shared: false,
|
||||
required: true,
|
||||
purposes: ['App functionality', 'Fraud prevention, security, and compliance', 'Personalization'],
|
||||
answer: 'Collected, not shared, required.',
|
||||
because:
|
||||
'The report’s note is text the user writes, and reporting, blocking and hiding are ' +
|
||||
'actions the app sends to the deployment, which keeps them. Reports exist so staff ' +
|
||||
'can act on abuse; blocks and hides change what this one reader is shown.',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'app-interactions',
|
||||
scope: 'app',
|
||||
@@ -746,7 +791,10 @@ export const collected = [
|
||||
title: 'Everything posted on the site',
|
||||
body:
|
||||
'Forum threads and replies, uploads, wiki revisions, moderation actions, warnings, ' +
|
||||
'reports and appeals — with the account that made each one. Where the operator has ' +
|
||||
'reports and appeals — with the account that made each one. A report keeps a copy ' +
|
||||
'of what the reported post or chat line said, so staff read what was reported even ' +
|
||||
'after it is edited or pruned. Each member’s blocks and the items they hid for ' +
|
||||
'themselves are kept against their account, and deleted with it. Where the operator has ' +
|
||||
'connected Discord, some of that crosses into Discord and is then also subject to ' +
|
||||
'Discord’s own terms.',
|
||||
retention: {
|
||||
@@ -755,7 +803,9 @@ export const collected = [
|
||||
'Soft-deleted forum uploads and Team activity have retention windows an admin ' +
|
||||
'sets; most other content is kept until somebody removes it.',
|
||||
},
|
||||
source: 'website server/db/schema.sql — team_forum_*, mod_actions, content_reports',
|
||||
source:
|
||||
'website server/db/schema.sql — team_forum_*, mod_actions, content_reports, ' +
|
||||
'user_blocks, user_hidden_items',
|
||||
},
|
||||
{
|
||||
id: 'deploy-engagement',
|
||||
|
||||
@@ -12,14 +12,14 @@
|
||||
"wrong protocol number in the first place."
|
||||
],
|
||||
|
||||
"verifiedOn": "2026-10-29",
|
||||
"verifiedOn": "2026-10-30",
|
||||
|
||||
"$comment_moduleApi": [
|
||||
"The one version every deployment shares, whichever game it runs. D66: it is the only",
|
||||
"version the homepage hero and the footer show — a protocol and a bundle belong to a game,",
|
||||
"so they appear on that game's own pages."
|
||||
],
|
||||
"moduleApi": "1.20.0",
|
||||
"moduleApi": "1.21.0",
|
||||
|
||||
"$comment_releases": [
|
||||
"Every repository whose release the site quotes, flat, so checkFacts.mjs reads them all",
|
||||
@@ -27,12 +27,12 @@
|
||||
],
|
||||
"releases": {
|
||||
"installer": "v0.8.1",
|
||||
"Android-app": "v0.6.0",
|
||||
"Android-app": "v0.7.0",
|
||||
"link": "v2.3.0",
|
||||
"Module-uo": "v1.4.0",
|
||||
"Module-uo": "v1.4.1",
|
||||
"Rust-Link": "v0.3.0",
|
||||
"Rust-Plugins": "v0.3.0",
|
||||
"Module-Rust": "v0.6.3",
|
||||
"Rust-Plugins": "v0.3.1",
|
||||
"Module-Rust": "v0.7.0",
|
||||
"runicnpc-rust": "v1.0.0"
|
||||
},
|
||||
|
||||
@@ -79,15 +79,15 @@
|
||||
"protocol": 14,
|
||||
"module": {
|
||||
"repo": "Module-Rust",
|
||||
"coreApi": "^1.19.0",
|
||||
"coreApi": "^1.21.0",
|
||||
"capabilities": ["rust", "servers", "killfeed", "leaderboard", "presence", "wipes", "identity", "map"]
|
||||
},
|
||||
"sidecarRepo": "Rust-Link",
|
||||
"pluginRepo": "Rust-Plugins",
|
||||
"bundle": {
|
||||
"tag": "2026.10.22",
|
||||
"tag": "2026.10.30",
|
||||
"sidecar": "v0.3.0",
|
||||
"plugin": "v0.3.0",
|
||||
"plugin": "v0.3.1",
|
||||
"oxideMin": "2.0.7585",
|
||||
"carbonMin": "2.0.259",
|
||||
"requiresPlugins": ["Kits", "ZoneManager"],
|
||||
@@ -120,17 +120,18 @@
|
||||
"",
|
||||
"`serviceable` is the one value here with no authority to check it against, and it is",
|
||||
"deliberately manual. It answers a question no API can: does the published build",
|
||||
"actually work. The org lead reports v0.5.0's does not, so the download block renders a",
|
||||
"'being replaced' state instead of a link, and flipping this to true is the single edit",
|
||||
"that turns the link back on once a working build is released. A check cannot run an",
|
||||
"APK; a person can, and this is where they record that they did."
|
||||
"actually work. v0.5.0's did not, and while false the download block renders a 'being",
|
||||
"replaced' state instead of a link. A check cannot run an APK; a person can, and this",
|
||||
"is where they record that they did. v0.7.0's was installed on an Android 16 emulator",
|
||||
"on 2026-10-31, connected to the public demo and read its Rust servers: true.",
|
||||
"When `asset` moves to a new release, set this back to false until someone has run it."
|
||||
],
|
||||
"androidApk": {
|
||||
"asset": "runic-gateway-0.6.0.apk",
|
||||
"asset": "runic-gateway-0.7.0.apk",
|
||||
"checksums": "SHA256SUMS",
|
||||
"minSdk": 29,
|
||||
"minAndroid": "10",
|
||||
"serviceable": false
|
||||
"serviceable": true
|
||||
},
|
||||
|
||||
"gitea": {
|
||||
|
||||
Reference in New Issue
Block a user