Add shard activity feed + admin live feed; fix public-feed leak

Front ends for the rest of the sidecar data, plus a security fix the live data
surfaced.

- lib/shardEvents.js: shared describe()/category/label for every event kind
  (sales, deaths & PvP, skills, fame/karma, quests, world, and staff kinds).
- Public /site/shard/activity (ShardActivity): the full event log with category
  filter tabs and a live tail (history + SSE merged, de-duped). Linked from the
  Shard page. Shard page now reuses the shared describe().
- Admin: a "Live feed (all events)" panel on the Shard admin page subscribing to
  the admin SSE channel — shows every kind incl. audit/cheat/login attempts.
  useShardFeed generalized to take a stream url; api.adminShardStreamUrl added.

Security fix: GET /public/shard/feed now restricts to the public-safe kind
allowlist (shardEvents.list gains a `kinds` IN-filter). Previously it returned
whatever was logged — including audit.* / cheat.* / link.request. Those are
still stored for the admin channel but never served publicly (verified: a
public request for audit.command returns 0 rows).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011qPmpmVH1xGCiZoz9m9vW3
This commit is contained in:
2026-07-11 03:10:03 -05:00
parent 74d2ead958
commit 49d0c1bd11
10 changed files with 249 additions and 48 deletions

View File

@@ -18,6 +18,7 @@ import About from './routes/public/About.jsx'
import Status from './routes/public/Status.jsx'
import Shard from './routes/public/Shard.jsx'
import ShardChar from './routes/public/ShardChar.jsx'
import ShardActivity from './routes/public/ShardActivity.jsx'
import Wiki from './routes/wiki/Wiki.jsx'
import WikiArticle from './routes/wiki/WikiArticle.jsx'
import CmsPage from './routes/public/CmsPage.jsx'
@@ -75,6 +76,7 @@ export default function App() {
<Route path="/site/about" element={<About />} />
<Route path="/site/status" element={<Status />} />
<Route path="/site/shard" element={<Shard />} />
<Route path="/site/shard/activity" element={<ShardActivity />} />
<Route path="/site/shard/char/:serial" element={<ShardChar />} />
<Route path="/wiki" element={<Wiki />} />
<Route path="/wiki/:slug" element={<WikiArticle />} />