wtclaude 4a0d8f0873
All checks were successful
PR Checks / server-tests (pull_request) Successful in 4s
PR Checks / client-build (pull_request) Successful in 3s
ci(module-uo): gate pull requests into main on server and client checks
Mirrors RunicGateway/website's pr-checks.yml, since this module is two npm
packages shaped like that repo's server/ and client/ and is loaded into that
repo's process: same Node 20, same npm ci + test + build, same concurrency
cancel and the same `PR Checks / *` status pattern for branch protection.

The repo has no module code yet — the API contract is settled in Phase 1 and
Phase 3 is what extracts the UO half of website/ into here — so each half's
gates are conditional on its package.json existing. Before the code lands the
jobs report green with a notice explaining why; the moment a package.json
appears they arm themselves with no edit to this file. That is the same guard
the installer repo used through its own planning phase, and it beats both
alternatives: leaving the repo ungated, or red-Xing every governance PR.

Landing it now also gets the status contexts reported once, which is what makes
them selectable when the `main` branch-protection rule is configured.

Deliberately not here yet, because there is nothing for them to act on until
Phase 3: the release workflow that publishes module-uo-<version>.tar.gz and its
sha256, the zero-internal-imports check, and the module's own frozen route
manifest. Each lands with the code it checks.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-10 02:40:23 -05:00

module-uo — the Ultima Online module for Runic Gateway

The Runic Gateway website is becoming game-agnostic: core keeps accounts, sessions, the wiki, posts, branding, theming and the admin panel, and everything that knows what a shard is moves out into an installable module. This repo is that module — the first one, and the reference for every module that follows.

        RunicGateway/website  (core — game-agnostic)
                 │  loads modules at boot, synchronously, from the filesystem
                 ▼
        ┌───────────────────────────────────────────┐
        │  module-uo   (>>> HERE <<<)               │
        │  shard status · spawn atlas · marketplace │
        │  governors · cliloc · town crier · uo-link│
        └───────────────────────────────────────────┘
                 │  server half: routers, models, schema fragment
                 │  client half: prebuilt ESM chunk, SPA routes + nav
                 ▼
        the shard bridge (RunicGateway/link → RunicGateway/servuo-plugins)

The module's id is uo — that is what appears in module.json, in the installed_modules table, in the modules/<id>/ path on disk and in the URL segment (/uo/*, /admin/uo/*, /player/uo/*). Module-uo is the repository; module-uo is the module and its release artifact.

Status: planning — no module code exists yet

This repo currently holds governance scaffolding only. The design of record is website/MODULE_SYSTEM.md in the docs repo — read it before opening a PR here. It defines the module API surface, the packaging, the state machine, the install/uninstall/purge model, and the phases.

Phase Where it happens State
0 — CI trigger fix, cut website edge, bootstrap this repo website, here 🟡 in progress
1 — module API contract (docs/website/MODULE_API.md) + the atlas spike docs, website blocking
2 — core scaffolding: loader, installed_modules, registries, client registry website
3 — extract the UO half of the site into this repo website, here
4 — delivery: the admin Modules screen + the Docker path website

Nothing lands here until Phase 1 has settled the contract this module is written against. Phase 3 is what fills the repo.

What it will contain

One repo, one bundle: the server half and the client half live side by side and version together, so a route and the screen that calls it can never be mismatched.

module.json            id, version, coreApi range, mounts, extensions
server/                routers, controllers, models, utils
server/db/schema.sql   idempotent fragment, replayed by core's ensureSchema()
server/db/purge.sql    destructive; only ever run by an explicit purge
client/src/            route components, nav registrations, feature provider
client/dist/           PREBUILT ESM chunk, built by CI — never by an operator

Release artifact: module-uo-<version>.tar.gz, plus a manifest carrying its sha256.

How it reaches an operator

An operator never builds anything. Installing a module is the WordPress-plugin experience: an admin-panel action, or a directory mounted into the Docker container — never a build step, because production runs a prebuilt, pull-only image. That constraint is why the client half ships as a prebuilt ESM chunk that resolves React from a window.__rg global rather than an import map (an import map must be inline, and the site's CSP is script-src 'self').

The installer is not the delivery path. It deploys the shard side — the plugin overlay and the uo-link sidecar — and never contacts the website. Module delivery is website-side only.

Compatibility

module.json declares a coreApi semver range, checked at boot against core's MODULE_API_VERSION. A mismatch fails loudly — the module is marked startup_failed and the site comes up without it, rather than mis-loading. This is a separate number from PROTOCOL_VERSION, which versions the shard wire protocol and says nothing about a website module.

A module that fails to load must never take the site down.

Repo What
thisRunicGateway/Module-uo The UO module: the game-specific half of the website.
RunicGateway/website Core — the site, admin panel and API that loads this module.
RunicGateway/link The uo-link sidecar — the network-facing half of the game bridge this module talks to.
RunicGateway/servuo-plugins The C# ServUO plugin that feeds the sidecar.
RunicGateway/installer Deploys the shard side. Not the module delivery path.
RunicGateway/docs All project documentation, including the module system design and this module's docs under modules/uo/.

Contributing

See CONTRIBUTING.md. Contributions are welcome, AI assistance must be disclosed, and security problems go to SECURITY.md rather than a public issue.

License

GNU General Public License v3.0 or later — see LICENSE.md.

Description
No description provided
Readme 713 KiB
v0.3.0 Latest
2026-08-12 04:11:54 +00:00
Languages
JavaScript 100%