diff --git a/website/MODULE_SYSTEM.md b/website/MODULE_SYSTEM.md index cc3bf85..3dc5104 100644 --- a/website/MODULE_SYSTEM.md +++ b/website/MODULE_SYSTEM.md @@ -291,12 +291,17 @@ than by review. ### 2.3 Module packaging — one repo, one bundle -`RunicGateway/module-uo`, GPL-3.0-or-later, CI shaped like the other repos. Server and client halves -live side by side and version together, so a route and the screen that calls it can never be -mismatched: +**`RunicGateway/Module-uo`** — `https://gitea.whitlocktech.com/RunicGateway/Module-uo.git`, note the +capital `M`, matching `Android-app`'s casing rather than the lowercase directory name. The repo +exists but is **empty** as of 2026-08-10: no branches, no initial commit. Its first commit needs the +usual scaffolding — `README.md`, `LICENSE.md` (GPL-3.0-or-later), `CONTRIBUTING.md` with the +AI-disclosure clause, the PR template, and CI. + +Server and client halves live side by side and version together, so a route and the screen that +calls it can never be mismatched: ``` -RunicGateway/module-uo +RunicGateway/Module-uo module.json id, version, coreApi range, mounts, extensions server/ routers, controllers, models, utils server/db/schema.sql fragment replayed by ensureSchema() @@ -307,6 +312,10 @@ RunicGateway/module-uo Release artifact: `module-uo-.tar.gz` plus a manifest carrying its `sha256`. +The module's **id** is `uo` — that is what appears in `module.json`, in `installed_modules`, in the +`modules//` path and in the URL segment. `Module-uo` is the repository; `module-uo` elsewhere in +this document names the module and its artifact, not the repo. + `module.json` declares a `coreApi` semver range, checked at boot against a `MODULE_API_VERSION` constant in core; a mismatch fails **loudly** rather than silently. This is a separate number from `PROTOCOL_VERSION`, which versions the shard wire and says nothing about a website module. @@ -364,6 +373,10 @@ Phase 1 prototypes exactly this before anything is committed to it (§2.7). ### 2.7 Phases +**Phase 0 — unblock CI and scaffold the repo.** Land the one-line `pr-checks.yml` trigger fix on +`website` `main` (§2.9), cut `edge` from `main`, and give `Module-uo` its initial commit (§2.3). +Nothing else can be trusted until the first of these is done. + **Phase 1 — API contract + spike (blocking).** Merge this document. Write the contract at `docs/website/MODULE_API.md`. Then a throwaway spike on an unmerged branch moving **`/api/v1/public/atlas/*`** behind the proposed surface — the smallest honest test: five routes, @@ -439,7 +452,37 @@ Two consequences, both accepted: separate Android module plan. App Links verification itself is unaffected — the manifest's intent filters only cover `/mobile/callback` and `auth/callback`. -### 2.9 Process obligations +### 2.9 Branch strategy — `edge`, then one cutover + +All website work lands on an **`edge`** branch and reaches `main` as a single cutover at the end, +the same shape used for [protocol v3](../link/v3.md) and the Android theming workstream. Nothing +half-extracted is ever on `main`: a core that has grown a module loader but not yet lost its UO code +is a coherent state, and a core mid-extraction is not. + +`edge` does not exist on `website` today — the protocol v3 cutover landed and the branch was cleaned +up, so it is cut fresh from `main`. `Module-uo` develops on its own `main` from its first commit; +it has no cutover to perform, since nothing depends on it until the website cutover lands. + +**Phase 0, and it blocks everything: the CI trigger.** `website/.gitea/workflows/pr-checks.yml` +declares: + +```yaml +on: + pull_request: + branches: [main] +``` + +So a PR into `edge` runs **no checks at all** — no server tests, no client build, no bot install. +This is the same trap that let all nine Android M12 phase PRs merge with zero CI. It matters more +here than it did there, because Phase 2's exit criterion *is* a CI result: a zero-line +`routes.manifest.json` diff and a passing test suite. Running the whole workstream blind and +discovering the breakage at cutover is the expensive version of this. + +The fix is one line — `branches: [main, edge]` — and it must land on `website` `main` **before** the +first module PR, not alongside it. `build-images.yml` is untouched: it triggers on push to `main`, so +images are published and production rolls at the cutover and at no point before it, which is correct. + +### 2.10 Process obligations Every server-side PR runs `npm run swagger`, `npm run routes:manifest` (the diff is reviewed, not merely regenerated) and `npm test`, and carries a matching edit to `BACKEND_DESIGN.md`. Module @@ -462,3 +505,5 @@ Conventional Commits, the AI-disclosure trailer, branches cut from an up-to-date | 8 | SPA pages namespaced: `/uo/*`, `/admin/uo/*`, `/player/uo/*` | §2.8 | | 9 | Clean break — no redirects, no nav-override migration; site is not public yet | §2.8 | | 10 | Client half loads as a prebuilt ESM chunk with React shared via a core global | §2.6 | +| 11 | Website work lands on `edge` and reaches `main` as one cutover at the end | §2.9 | +| 12 | The module repo is `RunicGateway/Module-uo`; the module id is `uo` | §2.3 |