feat(shard): admin write plane, help-page queue, and public champion board
All checks were successful
PR Checks / server-tests (pull_request) Successful in 10m20s
PR Checks / client-build (pull_request) Successful in 9m49s
PR Checks / bot-install (pull_request) Successful in 9m33s

Wire up the three uo-link sidecar surfaces that weren't integrated yet.

Champion spawns
- Ingest champ.update/champ.remove into a new shard_champs table (served from
  our own store, like online/houses); public /site/champs board with a nav link,
  live via the existing SSE feed (champ.* added to the public allowlist).

Staff write plane (admin + moderator)
- kick / ban / unban / broadcast via /admin/shard/*; actor is stamped server-side
  from the session, never the browser. Sidecar status codes mapped (403 disabled/
  protected, 404 unknown, 503/504 transient). admin.audit events are logged and
  surfaced at /admin/shard/audit.
- New admin "In-Game Ops" view (/admin/shard-ops), plus per-account Kick/Ban/Unban
  on the user-detail and character views (ShardAccountActions, self-gated to staff).

Help-page (support) queue
- Ingest page.new/updated/closed into a new shard_pages table; respond/close via
  /admin/shard/pages/*. Champ board and page queue are snapshotted from the
  sidecar's /champs and /pages on every WS (re)connect (guarded so a failed call
  never wipes local state).

Verified live end-to-end against MariaDB + the Rust sidecar + ServUO; unit tests
cover ingest routing (shardIngest.champsPages.test.js). Swagger regenerated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0114TpmrNW4wNXsHq5CR72jQ
This commit is contained in:
2026-07-14 13:16:10 -05:00
parent 2dc360ca48
commit c31553aeb6
25 changed files with 2188 additions and 8 deletions

View File

@@ -45,6 +45,24 @@ export function describe(ev) {
return 'Shard shut down'
case 'server.crashed':
return `Shard crashed${p.error ? `: ${p.error}` : ''}`
case 'champ.update': {
const where = p.name || p.type || 'A champion spawn'
if (p.status === 'active' && p.bossUp) return `${where}: boss is up${p.boss ? ` (${p.boss})` : ''}`
if (p.status === 'active') return `${where} is active${p.level != null ? ` — level ${p.level}` : ''}`
if (p.status === 'cooldown') return `${where} is on cooldown`
return `${where} is ${p.status || 'idle'}`
}
case 'champ.remove':
return `A champion spawn ended`
// Support (help-page) queue + in-game moderation (admin channel only)
case 'page.new':
return `New ${p.type || 'help'} page from ${nameOf(p.sender)}`
case 'page.updated':
return `Help page from ${nameOf(p.sender)} updated${p.handled ? ' (claimed)' : ''}`
case 'page.closed':
return `Help page ${p.pageId || ''} closed`
case 'admin.audit':
return `${p.actor || 'Staff'} ${p.action || 'acted'}${p.target ? ` on ${p.target}` : ''}${p.origin ? ` [${p.origin}]` : ''}`
// Staff / sensitive (admin channel only)
case 'audit.set':
return `${nameOf(p.staff) || 'Staff'} set ${p.prop} on ${p.target || p.targetSerial} (${p.old}${p.new})`