From 3f5cd72ed6fe573161e5439b0918257ed32b9092 Mon Sep 17 00:00:00 2001 From: wtclaude Date: Fri, 30 Oct 2026 09:04:26 -0500 Subject: [PATCH] docs(kit): re-pin to core 1.21.0 and teach report targets ci/core-ref.json moves from 7bd93b8 (1.20.0) to f13b8fe (1.21.0, website#233, report, block and hide). Chapter 2 gains a section on registerReportTargets, registerGameIdentities and ctx.safety, and its call count becomes twenty-three. template/module.json's coreApi becomes ^1.21.0 for the equality check; the template declares none of the new members. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY --- book/02-website-module.md | 43 ++++++++++++++++++++++++++++++++++++++- ci/core-ref.json | 12 ++++++++++- template/module.json | 2 +- 3 files changed, 54 insertions(+), 3 deletions(-) diff --git a/book/02-website-module.md b/book/02-website-module.md index 3b3b5b3..eeef834 100644 --- a/book/02-website-module.md +++ b/book/02-website-module.md @@ -147,7 +147,7 @@ statement of your dependencies, and it makes a test double for it — see ## What you register -Twenty-one calls, all synchronous and all listed in [§2.4][api]: fifteen +Twenty-three calls, all synchronous and all listed in [§2.4][api]: seventeen registrations, the two lifecycle hooks, the two identity-link hooks, the demo's seed hook, and the account-deletion hook. Five of the registrations are the event system's, and [chapter 5](05-events.md) has those. What @@ -571,6 +571,46 @@ api.onUserDeleting(async ({ userId, deletedBy }) => {}) // deletedBy: 'self' | ' needs `coreApi` `^1.20.0`, because an older core has no `api.onUserDeleting`, and calling a missing function throws during `register()`. +### When members report, hide or block what your game shows + +If your module shows what players wrote, such as chat from the game, members can +report it, hide it for themselves, and block whoever wrote it, and staff can hide +it for everyone (`MODULE_API_VERSION` 1.21.0, [`USER_SAFETY.md`][safety]). Core +keeps the Reports queue and each member's blocks and hides. You keep the content, +and you tell core three things about it: + +```js +api.registerReportTargets([{ id: 'mygame.chat', label: 'Chat line', snapshot, hide, unhide }]) +api.registerGameIdentities([{ kind: 'steam', label: 'Steam account', ownersOf }]) +// and, from your own per-reader routes: ctx.safety.forViewer(userId), ctx.safety.staffAmong(userIds) +``` + +- **`snapshot({ targetId, viewer })` answers for that reader, and `null` covers two + cases.** An item that is gone and an item they could not have seen get the same + `null`, so core gives them the same 404. Otherwise a report or a block would tell + anybody who said line 4410 on a server whose player list is hidden from them. Run + the same visibility check your page runs. +- **Name the author by their site account when they have one.** `author.userId` is + the linked account and `author.identity` is the game id. `ownersOf(ids)` answers + which ids are linked. A block then lands on the account, and only an unlinked id + is blocked as itself. Core rewrites that block as an account block once the id + links, so you never have to. +- **Filter on the server, in your query.** A route that shows the content to + signed-in readers calls `ctx.safety.forViewer(userId)` and leaves out what that + reader blocked or hid. Do it in the `WHERE` clause, so a page of 100 is still 100 + long, and keep the route per-viewer (`Cache-Control: private`), or a shared cache + hands one reader's filter to the next. If your page offers *Block*, mark each item + with whether it can be blocked. Use `ctx.safety.staffAmong` for that, because + staff cannot be blocked. +- **Hide for everyone is a flag you keep.** `hide` is called from core's queue. + Leave the item out for everyone but staff, and show it to staff marked, with an + undo where it lives. Core never calls `unhide` itself. +- **Each call has 5 s.** A module that does not answer is a 503 to the member, + never a silent success. Declaring any of it needs `coreApi` `^1.21.0`. + +Module-Rust's `server/safety.js` is a complete worked example: chat lines, Steam +ids and the feed's own filter. + ### On a public demo site A site can run as a public demo (`MODULE_API_VERSION` 1.18.0). Anybody signs in with @@ -939,3 +979,4 @@ the next chapter is for. [api]: https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/website/MODULE_API.md [acceptance]: https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/modules/kit-acceptance.md +[safety]: https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/website/USER_SAFETY.md diff --git a/ci/core-ref.json b/ci/core-ref.json index b94128d..a3de377 100644 --- a/ci/core-ref.json +++ b/ci/core-ref.json @@ -1,10 +1,20 @@ { "repo": "https://gitea.whitlocktech.com/RunicGateway/website.git", "branch": "main", - "ref": "7bd93b8bb0da734a642587f256d10c523ca39bea", + "ref": "f13b8fe1fec9dc330a985430b8bd4f67c9ec26c5", "why": [ "The core this kit is written against, pinned to a commit rather than a branch.", "", + "2026-10-30: moved from 7bd93b8 (1.20.0) to f13b8fe (1.21.0, website#233,", + "report, block and hide, USER_SAFETY.md). Chapter 2 was read again:", + "- 1.21.0: api.registerReportTargets, api.registerGameIdentities and", + " ctx.safety.forViewer / staffAmong (chapter 2 gains a section, and its call", + " count becomes twenty-three).", + "website#233 is the only core change in the window. The template declares", + "none of the new members, so nothing it does changed meaning; module.json's", + "coreApi becomes ^1.21.0 for the equality check. The real core run was", + "repeated at this ref, with the template as the only module in the directory.", + "", "2026-10-30: moved from 69998ec (1.19.0) to 7bd93b8 (1.20.0, website#232,", "account deletion, ACCOUNT_DELETION.md). Chapter 2 was read again:", "- 1.20.0: api.onUserDeleting (chapter 2 gains a section, and its call count", diff --git a/template/module.json b/template/module.json index 060967f..a6d8c00 100644 --- a/template/module.json +++ b/template/module.json @@ -2,7 +2,7 @@ "id": "examplegame", "name": "Example Game", "version": "0.1.0", - "coreApi": "^1.20.0", + "coreApi": "^1.21.0", "server": "server/index.js", "client": { "entry": "client/dist/entry.js" }, "schema": "server/db/schema.sql", -- 2.49.1