docs(modules): module-rust phase 1 as built — the transport, and three org-lead decisions

Adds docs/rust-link/, the canonical spec for the Rust bridge: PROTOCOL.md (the
game link and the website API) and INTEGRATION.md (standing it up by hand, and
which of the three components is wrong when it does not work). A new top-level
directory mirroring link/, which is decision D1 below -- it keeps the uo/link
symmetry and keeps module docs separate from bridge docs.

Records phase 1 in PLAN.md as section 13. Both criteria met: a server.hello
produced by the live Rust rig travelled game -> sidecar -> module -> the public
website API, killing the sidecar left the game untouched, and all five guards are
green on the module skeleton.

Three org-lead decisions this phase needed, none settled by section 2:

* D1 -- the bridge docs live at docs/rust-link/.
* D2 -- loopback is the ONLY trust boundary on the game link, no token, exactly
  as on the ServUO bridge. Argued the other way on the grounds that Rust servers
  are far more often on GSPs; overruled, and the consequence is now written down
  as the mistake rather than defended against.
* D3 -- the plugin reads Oxide's own config file, so it lands inside the phase-7b
  config editor for free. The argument against -- that editing Host/Port from the
  website could cut the link carrying the edit -- becomes that phase's guard
  rather than a reason for a second config mechanism.

Section 11.3 is corrected in place: it read module.json's  as held
against reality by the loader in the way  is. Only half true. The loader
checks that a named slot EXISTS and never that the module filled it --
checkDeclared covers mounts alone -- and only ONE of R13's two slots can be
declared there at all, because site.footer.status is a CLIENT slot and naming it
fails the load outright.

Section 13.3 records five defects a running server found that no test could,
including a bootId that regenerated on every plugin load rather than every server
start -- which would have asked core to reconcile its whole ledger on every
oxide.reload, for a world that never moved.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4
This commit is contained in:
2026-09-15 19:55:05 -05:00
parent 80c7a9dcd1
commit 469e06af56
4 changed files with 717 additions and 1 deletions

View File

@@ -10,6 +10,7 @@ so they live in one place, independent of either codebase.
website/ docs from the website core (Node/Express + MariaDB + React/Vite)
modules/ docs for installable game modules — one directory per module id
link/ docs from the ServUO bridge (C# plugin + Rust sidecar + Node WS)
rust-link/ docs from the Rust bridge (Oxide plugin + Rust sidecar)
android/ docs from the native Android client (Kotlin + Jetpack Compose)
installer/ docs for the installer that deploys a shard's bridge components
ci/ cross-cutting CI/quality notes
@@ -76,6 +77,17 @@ particular game; a module is what makes it a site *for* one.
| [link-README.md](link/link-README.md) | Snapshot of the link repo's README |
| [PROJECT_TREE.md](link/PROJECT_TREE.md) | Auto-generated snapshot of the repo's tracked file layout |
### `rust-link/`
The same pair of contracts as `link/`, for Rust rather than Ultima Online: an Oxide plugin that
dials out to a sidecar, and a sidecar the website reads. The two bridges are **independent** — they
share a shape and nothing else, so neither document is a fallback for the other.
| Doc | What it covers |
|---|---|
| [PROTOCOL.md](rust-link/PROTOCOL.md) | **Canonical** — the game link and the website API, the four declaration sites of the wire version, and what protocol 1 defines |
| [INTEGRATION.md](rust-link/INTEGRATION.md) | Standing the bridge up by hand, and which of the three components is wrong when it does not work |
### `android/`
| Doc | What it covers |
|---|---|