# rust-link The **sidecar** half of the Runic Gateway bridge for [Rust](https://rust.facepunch.com/). It terminates the loopback link from a Rust server's Oxide bridge plugin and exposes the WebSocket + REST surface the website consumes. It is the mirror of [`RunicGateway/link`](https://gitea.whitlocktech.com/RunicGateway/link), which does the same job for Ultima Online, and it keeps that bridge's central invariant unchanged: > **The game server is never reachable from the website.** The plugin dials *out* to this process; > this process owns the listener. Only the sidecar is exposed, and only the website's backend talks > to it. ``` Rust server + Oxide (RunicGateway/Rust-Plugins, C#) │ loopback TCP 127.0.0.1:7799, newline-delimited JSON, bidirectional │ the PLUGIN dials out (the game opens no listening port for us) ▼ rust-link sidecar (this repo, Rust) ← the only network-facing bridge component │ WebSocket (live feed) + REST (point-in-time reads), bearer-token auth ▼ website backend + module-rust (RunicGateway/Module-Rust, Node) ``` ## One server, one sidecar This binary serves **exactly one** Rust game server. A community running six servers runs six pairs, each with its own port, database and token; `module-rust` holds six clients and the website core never learns there is more than one. Nothing here is multiplexed, and nothing here should become multiplexed. ## Build and run ```bash cd sidecar cargo build --release # → target/release/rust-link-sidecar cargo run # info logging; writes sidecar.toml (with a generated token) on first run RUST_LOG=debug cargo run # verbose, including heartbeats ``` Everything is configured from `sidecar.toml` — nothing is compiled into the binary. **Auth is always on**: a blank token is generated and written back on first start, so there is no state in which this process listens without one. `--print-config` resolves the configuration and prints it as JSON, which is how an installer reads the token back without scraping a log. See [`sidecar/README.md`](sidecar/README.md) for the configuration reference and the endpoint list. ## The protocol is a contract The loopback JSON protocol (plugin ↔ sidecar) and this sidecar's HTTP/WS API (sidecar ↔ website) are **versioned compatibility contracts**, not build dependencies. `PROTOCOL_VERSION` lives in [`sidecar/src/main.rs`](sidecar/src/main.rs); every response carries `X-RustLink-Version`, and a client that declares a different one is refused `409` rather than served something it will mis-parse. A version is declared in **three** places and they must agree: | Where | Repo | |---|---| | `PROTOCOL_VERSION` | this repo | | `overlay.toml` | [`RunicGateway/Rust-Plugins`](https://gitea.whitlocktech.com/RunicGateway/Rust-Plugins) | | `module.json` | [`RunicGateway/Module-Rust`](https://gitea.whitlocktech.com/RunicGateway/Module-Rust) | The canonical spec is [`docs/rust-link/`](https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/rust-link). If you add or change an event or a command, update all three repos **and** the spec in the same change. ## Licence GPL-3.0-or-later. See [LICENSE.md](LICENSE.md).