docs(admin): the engagement rules screen, and the privacy inventory an engagement mailer changes
Engagement Phase 12a. The site had pages for where a message goes (Notifications and
email) and what it says (Message templates), and nothing at all for what makes one get
sent -- the four Engagement screens the workstream built.
New page: Engagement rules. Rules, Audiences, the trigger catalog and the send log on
one page, sitting between the two it joins up. Templates already has its own page and
Suppressions is in Troubleshooting, so neither is repeated here.
Two things it exists to state plainly:
* Every rule ships disabled, including the ones a module brings. "Installed" is not
"on", and an upgrade whose Team mail went quiet is the same fact.
* The ceiling is a TREE, not a ladder. The tempting reading -- a staff-only event
could obviously also go to one person -- is wrong, and the example is the argument:
"one person" for cheat detection is the player it was detected on.
Troubleshooting gains the symptom that page answers ("nothing is sent for one
particular event"): the rule is off, the rule is dormant, its own cooldown held it, or
the audience is empty.
Privacy: two rows the engagement work makes necessary, and one sentence it made false.
* app-content claimed "Nothing is cached for offline use". Phase 8 shipped a DataStore
snapshot of the inbox, so it was untrue -- and that row feeds the generated Play Data
Safety answers, which is a store-review matter rather than a doc nit. The snapshot now
has its own row and its own Play mapping (Messages / Other in-app messages; not
collected by us, stored on the device), and app-content's claim is narrowed to
everything else.
* deploy-engagement, for the deployment scope: an address is now used for more than
getting into an account, there is a delivery log holding a one-way hash of it, and
there is a suppression list. Its retention line says what is true rather than what a
reader assumes -- none of these tables has a retention sweep.
PLAY_DATA_SAFETY.md regenerated from the inventory; legal.lastUpdated moved with the page
it dates.
Verified: the whole `verify` chain green -- checkSidebar (plannedSidebar moved with the
live tree), checkFacts 19/19, checkQuickstart 59, checkReference 22, checkLinks 2605,
checkA11y, checkCsp, playDataSafety --check, 42 + 7 tests. Read in a browser as well, in
the served build.
AI-assisted: written with Claude Code.
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -285,9 +285,10 @@ export const collected = [
|
||||
title: 'Everything you read and post in the app',
|
||||
body:
|
||||
'Forum posts, Team activity, character and shard information, notification ' +
|
||||
'preferences: all of it is a live read or write against the deployment. Nothing is ' +
|
||||
'cached for offline use and nothing is duplicated anywhere else — the app with no ' +
|
||||
'signal is an app with no content, which is a limitation and also an accurate ' +
|
||||
'preferences: all of it is a live read or write against the deployment. Apart from ' +
|
||||
'the notification snapshot described in the next entry, nothing is cached for ' +
|
||||
'offline use and nothing is duplicated anywhere else — the app with no signal is ' +
|
||||
'an app with almost no content, which is a limitation and also an accurate ' +
|
||||
'description of where the data lives.',
|
||||
retention: {
|
||||
summary: 'Held by the deployment, under its operator’s policy',
|
||||
@@ -304,6 +305,40 @@ export const collected = [
|
||||
'access and no way to obtain one.',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'app-inbox-cache',
|
||||
scope: 'app',
|
||||
title: 'A snapshot of your notifications, so the inbox opens without a signal',
|
||||
body:
|
||||
'The app keeps the most recent notifications it has already fetched — at most ' +
|
||||
'thirty, and only the first page — on the device, so opening the inbox shows you ' +
|
||||
'what you had rather than a spinner. It is a copy of what the deployment already ' +
|
||||
'sent you and it is refreshed from there; nothing is written here that was not ' +
|
||||
'read from your own account. It is scoped to the account that fetched it, so a ' +
|
||||
'second person signing in on the same phone is never shown the first one’s ' +
|
||||
'messages.',
|
||||
retention: {
|
||||
summary: 'Until you sign out, or the thirty are pushed out by newer ones',
|
||||
detail:
|
||||
'Signing out deletes the snapshot outright. It lives in the app’s ordinary ' +
|
||||
'preference store rather than the encrypted one — sign-in tokens are the thing ' +
|
||||
'that store is for — which is worth stating plainly: on a device where someone ' +
|
||||
'has root, these are readable, and they are notification bodies rather than ' +
|
||||
'credentials.',
|
||||
},
|
||||
source: 'core/inbox/DataStoreInboxCache.kt, data/repository/AuthRepository.kt',
|
||||
play: {
|
||||
category: 'Messages',
|
||||
type: 'Other in-app messages',
|
||||
collected: false,
|
||||
shared: false,
|
||||
answer: 'Not collected by us. Stored on the device only.',
|
||||
because:
|
||||
'The snapshot is written on the phone from data the deployment had already ' +
|
||||
'delivered. It is not uploaded anywhere, and no server we operate is on either ' +
|
||||
'end of it.',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'app-no-analytics',
|
||||
scope: 'app',
|
||||
@@ -401,6 +436,34 @@ export const collected = [
|
||||
},
|
||||
source: 'website server/db/schema.sql — team_forum_*, mod_actions, content_reports',
|
||||
},
|
||||
{
|
||||
id: 'deploy-engagement',
|
||||
scope: 'deployment',
|
||||
title: 'Notifications, and the record of what was sent',
|
||||
body:
|
||||
'An operator can have the site notify people about things that happen on it — on ' +
|
||||
'the site, by email, by push — so an address is now used for more than getting ' +
|
||||
'into an account. Each member chooses this per notification and per channel, and ' +
|
||||
'email and push are both off until they ask for them. Alongside that the site ' +
|
||||
'keeps a delivery log: what fired, which account, which channel, whether it ' +
|
||||
'arrived, and a one-way hash of the address rather than the address. Addresses ' +
|
||||
'that bounce or are reported as spam go on a suppression list, which stores the ' +
|
||||
'same hash plus a masked form (`d***@example.com`, never the local part) so an ' +
|
||||
'operator can see what was suppressed without the list becoming a second address ' +
|
||||
'book.',
|
||||
retention: {
|
||||
summary: 'Kept until the operator removes them; nothing here expires on its own',
|
||||
detail:
|
||||
'Stated plainly because it is the answer people assume the other way round: ' +
|
||||
'the delivery log, the suppression list and the per-person rate limits have no ' +
|
||||
'retention sweep, so they are as long as the site is old. Deleting an account ' +
|
||||
'detaches its rows from it rather than deleting them — a delivery history stops ' +
|
||||
'naming a person, and a suppressed address stays suppressed.',
|
||||
},
|
||||
source:
|
||||
'website server/db/schema.sql — engagement_sends, engagement_suppressions, ' +
|
||||
'notification_channel_prefs',
|
||||
},
|
||||
{
|
||||
id: 'deploy-game-data',
|
||||
scope: 'deployment',
|
||||
|
||||
Reference in New Issue
Block a user