refactor(modules)!: move the UO server half out to module-uo

40 files, ~9,674 lines, 27 of 68 tables. Core no longer contains anything that
knows what a shard is.

BREAKING for a deployment only in the sense that the module must be installed
for these URLs to answer -- no URL moved. routes.manifest.json goes 228 -> 158
public routes here, and the 70 that left reappear byte-identical when the module
is loaded: verified by generating the manifest against core+module and diffing
it against the pre-extraction file. Zero missing, zero added, and routes.guards
identical across all 228, so no auth gate moved either.

The five tier mounts are gone from public/admin/player index.js and are still
served: the loader mounts them onto the same routers after every core mount.
That ordering is also what keeps the prefixes unclaimable -- the collision check
asks the live router what core owns, so a second module claiming /shard is
rejected against the mounts actually present rather than against a list.

server.js loses its eight UO call sites to the module's onBoot/onShutdown.
schema.sql loses its 27 shard_*/uo_link_* statements; the two that FK into users
are why the fragment replays AFTER core's schema, and no core table ever
referenced a module table, which is what makes core still able to boot alone.

Verified against a running server with the module installed: it loads, mounts
five prefixes, replays 35 statements, warms up and reaches `started`; public
shard and atlas routes answer 200 with real data (800 creatures, 6,455
spawners), admin and player answer 401 from core's tier gates, and the extension
slot answers at /admin/users/:id/shard/*. Core's own SPA renders the shard and
atlas pages unchanged against the module-served API, with no console errors and
no CSP reports.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-08-11 12:08:03 -05:00
committed by Claude
parent f50541f374
commit 39d731d87a
9 changed files with 27 additions and 5223 deletions

View File

@@ -27,8 +27,6 @@ const postsRouter = require('./posts.router')
const uploadsRouter = require('./uploads.router')
const wikiRouter = require('./wiki.router')
const pagesRouter = require('./pages.router')
const shardRouter = require('./shard.router')
const uoLinkRouter = require('./uoLink.router')
const emailRouter = require('./email.router')
const discordBotRouter = require('./discordBot.router')
const settingsRouter = require('./settings.router')
@@ -64,12 +62,14 @@ adminRouter.use('/posts', postsRouter)
adminRouter.use('/uploads', uploadsRouter)
adminRouter.use('/wiki', wikiRouter)
adminRouter.use('/pages', pagesRouter)
// Ops and configuration. /shard mixes tiers on one prefix — self-service game
// account linking (no extra gate) alongside modAccess in-game staff ops — so
// one router owns the prefix and gates per route. The rest are admin-only.
// /admin/shard/pages is the in-game help-page queue, unrelated to /admin/pages.
adminRouter.use('/shard', shardRouter)
adminRouter.use('/uo-link', uoLinkRouter)
// Ops and configuration.
//
// `/shard` and `/uo-link` are absent here and are still served: they are
// module-uo's, mounted onto this same router by the loader after every core
// mount above (MODULE_API.md §2.4). The URLs did not move — the code did. That
// ordering is also what makes the prefixes unclaimable by anyone else: the
// loader asks this live router what core owns, so a second module claiming
// `/shard` is rejected against the mounts actually present, not against a list.
adminRouter.use('/email', emailRouter)
adminRouter.use('/discord-bot', discordBotRouter)
adminRouter.use('/settings', settingsRouter)