First commit for the UO module — the game-specific half of the Runic Gateway
website, extracted from core so that core can become game-agnostic. Phase 0 of
the module system plan (docs/website/MODULE_SYSTEM.md §2.7) calls for this repo
to get its initial commit before any module work starts.
Governance scaffolding only; no module code. The design of record settles the
API surface in Phase 1 and Phase 3 is what fills the repo, so writing module
code now would be writing against a contract that does not exist yet.
- README.md what module-uo is, the phase table, the packaging layout,
and why an operator never builds anything
- CONTRIBUTING.md planning status, the dev loop (a module is not runnable on
its own), the zero-internal-imports and one-path-segment
rules, schema fragments instead of migrations
- SECURITY.md private reporting, plus the module-specific notes: the
module boundary is not a security boundary, access control
lives in core, and the uo-link token stays write-only
- CODE_OF_CONDUCT.md, CONTRIBUTORS.md, LICENSE.md (GPL-3.0-or-later),
PR + issue templates — the same set every repo in the org carries
- .gitignore Node-shaped; client/dist/ is ignored deliberately, since it
is a release artifact built by CI, not a source artifact
CI lands next, in a PR, mirroring how the installer repo was bootstrapped: an
empty repo cannot take a pull request, but everything after it can.
Co-Authored-By: Claude <noreply@anthropic.com>
101 lines
5.6 KiB
Markdown
101 lines
5.6 KiB
Markdown
# 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`](https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/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](https://gitea.whitlocktech.com/RunicGateway/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.
|
|
|
|
## Related repos
|
|
|
|
| Repo | What |
|
|
|------|------|
|
|
| **this** — `RunicGateway/Module-uo` | The UO module: the game-specific half of the website. |
|
|
| [RunicGateway/website](https://gitea.whitlocktech.com/RunicGateway/website) | Core — the site, admin panel and API that loads this module. |
|
|
| [RunicGateway/link](https://gitea.whitlocktech.com/RunicGateway/link) | The **uo-link sidecar** — the network-facing half of the game bridge this module talks to. |
|
|
| [RunicGateway/servuo-plugins](https://gitea.whitlocktech.com/RunicGateway/servuo-plugins) | The **C# ServUO plugin** that feeds the sidecar. |
|
|
| [RunicGateway/installer](https://gitea.whitlocktech.com/RunicGateway/installer) | Deploys the shard side. Not the module delivery path. |
|
|
| [RunicGateway/docs](https://gitea.whitlocktech.com/RunicGateway/docs) | All project documentation, including the module system design and this module's docs under `modules/uo/`. |
|
|
|
|
## Contributing
|
|
|
|
See [CONTRIBUTING.md](CONTRIBUTING.md). Contributions are welcome, AI assistance must be disclosed,
|
|
and security problems go to [SECURITY.md](SECURITY.md) rather than a public issue.
|
|
|
|
## License
|
|
|
|
**GNU General Public License v3.0 or later** — see [LICENSE.md](LICENSE.md).
|