docs(modules): audit the plan against the whole contract, not just the game-facing chapters

The first draft of the phase list was built from chapters 3-5 and under-planned
the website module by a wide margin. The template registers eight of the ten
non-event registrations; the plan covered three.

Unplanned and now recorded: registerExtension, registerNotificationStreams,
registerEventTriggers, registerAudiences, registerEngagementSeeds,
registerAnnounceLeg, registerPostHook, registerSlashCommands - with triggers,
audiences and seeds being a matched set rather than three independent gaps.
Also unplanned: purge.sql, mount prefix choice, the swagger fragment and its
staleness check, the vite alias/shim mechanism the kit calls the highest-risk
mechanical detail in the system, checkImports, and the entire packaging and
release path - there was no packaging phase at all.

On the client: declareModuleSlot, which the kit says is needed the moment a game
has anything like a guild, so it belongs in the Teams phase; registerFeatureProvider;
and the UI kit discipline that has caught this project twice already (PublicLayout
needs shell, PageHeader silently drops unknown props).

Beyond the module: the asset bridge, which Rust's item icons and 2,590 skin ids
fit exactly; the .profile landing page, owed whenever repos are added and three
just were; runicgateway.com, for which a second game is a headline change; and
the Android app, which feature-detects capabilities and must render a site whose
module it has never heard of.

Section 8 carries the eight questions the plan cannot answer for itself.
This commit is contained in:
2026-09-15 11:45:04 -05:00
parent 839e5d05a8
commit a4544ba5f2

View File

@@ -353,4 +353,95 @@ is invalidated at once, and **"gone, and that is fine" is a success**, not a fai
- **`start.bat`'s RCON password is `letmein` in plaintext with `rcon.web 1`.** Acceptable on a
loopback dev rig, and it must never be the shape anything published copies.
## 7. Contract coverage audit
Added 2026-09-15 after re-reading the whole kit rather than only chapters 35. **The first draft of
§5 was built from the game-facing chapters and under-planned the website module by a wide margin.**
Every element of the contract is listed below with where it lands; the unplanned ones are the point
of the table.
### The server handshake — ten registrations plus two hooks (ch. 2)
| Call | Planned? | Where |
|---|---|---|
| `registerRoutes` | yes | 3 |
| `registerTeamProvider` | yes | 6 |
| `registerEventBudgets` / `OptionSources` / `Leases` / `Actions` | yes | 78 |
| `onBoot` / `onShutdown` | **implicit only** | make explicit in 1 |
| `registerExtension` | **no** | the dry run's own manifest declared `admin.users.detail` |
| `registerNotificationStreams` | **no** | — |
| `registerEventTriggers` | **no** | — |
| `registerAudiences` | **no** | — |
| `registerEngagementSeeds` | **no** | — |
| `registerAnnounceLeg` | **no** | — |
| `registerPostHook` | **no** | — |
| `registerSlashCommands` | **no** | — |
**The template registers eight of these and the plan covered three.** Triggers, audiences and
engagement seeds are in `template/server/index.js` as a matched set — a trigger declares the payload
and its audience `ceiling`, an audience resolves people over module data, and seeds ship the bodies
and rules. None of the three was in §5.
### The bundle's own parts
| Part | Planned? | Note |
|---|---|---|
| `module.json` `id` / `coreApi` / `capabilities` | yes | 1, 3 |
| **`mounts` and prefix choice** | **no** | shares one namespace with core's, and the loader's probe cannot see core's root-mounted endpoints |
| `schema.sql` | yes | 2 |
| **`purge.sql`** | **no** | required whenever a schema ships |
| **`swagger-fragment.json` + generator + `check:swagger`** | **no** | fixed filename, merged verbatim, must be committed and checked current |
| **`vite.config.js` aliases / shims / `checkExternals`** | **no** | the kit calls this the highest-risk mechanical detail in the system |
| **`checkImports.js`** | **no** | the guard that makes a reach into core's tree fail the build |
| **`release.yml`, install manifest, `sha256`, host allowlist** | **no** | there was no packaging phase at all |
### The client half
| Part | Planned? | Note |
|---|---|---|
| `registry.registerRoutes` / `registerNav` | yes | 3 |
| **`declareModuleSlot`** | **no** | the kit: *"you will need it the moment your game has anything like a guild"* — so phase 6 |
| `registerFeatureProvider` | **no** | how a nav row becomes conditional |
| **UI kit discipline** | **no** | `PublicLayout` needs `shell`; `PageHeader` takes `eyebrow`/`title`/`lead`/`center` and drops unknown props silently |
### Beyond the module
| Item | Planned? | Note |
|---|---|---|
| Sidecar rpc correlation | implicit | needed by 78; state it in 1 |
| **Asset bridge (ch. 3 §2b)** | **no** | Rust's item icons and 2,590 skin ids are exactly the "content already on the game host" case |
| **`.profile` landing page** | **no** | three repos added is precisely when it is owed |
| **`runicgateway.com`** | **no** | a second game is a headline platform change |
| **Android app** | **no** | it feature-detects `capabilities` and must render a site whose module it has never heard of |
| `docs/` | yes | 11 |
### What this does to the phase list
The gaps are not evenly distributed: most land in the website module, which the original §5 treated
as three phases and which the kit treats as the bulk of the work. The phase list needs a packaging
phase, a notifications-and-engagement phase, and explicit bundle-mechanics work inside phase 1 —
plus decisions on the optional surfaces (slash commands, extension slots, the asset bridge) before
they can be scheduled. Those decisions are §8.
## 8. Questions this plan cannot answer for itself
Open, in rough order of how much they change the schedule. None is blocking phase 0.
1. **Notifications and engagement** — does v1 ship triggers, audiences and engagement seeds, or is
that a later workstream? The template treats them as core furniture; skipping them means a Rust
site that cannot mail anybody about anything.
2. **Discord slash commands** — the platform has a bot and `registerSlashCommands` exists. Does the
Rust module claim any?
3. **Extension slots** — the dry run's manifest declared `admin.users.detail` (a user's Rust
identities inside core's admin user page). Keep it?
4. **The asset bridge** — item icons and skins over the bridge, or not in v1? It is a whole
protocol's worth of work and the site renders without it.
5. **Android** — does the app get Rust support in this workstream, or does it stay UO-only until the
module ships?
6. **Which mount prefixes**, given they share a namespace with core's own.
7. **Server scale** — how many Rust servers should the first release support in the UI? The dry run
says the module holds one client per server; the pages differ a lot between one and six.
8. **Wipe retention** — when a wipe truncates gameplay data, what survives? All-time rollups, or a
clean slate each month?
[kit]: https://gitea.whitlocktech.com/RunicGateway/Integration-kit