All checks were successful
PR Checks / rust-gates (pull_request) Successful in 7m52s
Phase 0.2 of the installer plan (docs/installer/PLAN.md §5). The installer has to drive this binary non-interactively, and today it cannot: the auth token is only readable by scraping the startup log, the config path can only be named through an environment variable, and a relative db path follows the process working directory — which a service manager, not the operator, chooses. - Add a four-flag CLI (cli.rs): --print-config, --config <PATH>, --version, --help. Hand-rolled; an argument-parsing dependency would be larger than the code it replaced. An unrecognized flag exits 2 rather than starting a sidecar that is not the one that was asked for. - --print-config resolves the configuration exactly as a normal start does — including writing a missing config file and generating a blank auth token — and prints it as JSON on stdout: versions, protocol, both bind addresses, ws path, resolved db path, and the token. config_created / token_generated let a re-run tell "read an existing install" from "provisioned a new one". The log subscriber is deliberately not started in this mode, so the document is the whole output. - Anchor a relative [store].path to the config file's directory instead of the CWD, and report resolved absolute paths. A unit pinning UOLINK_CONFIG now keeps its database beside its config rather than in %SystemRoot%\System32 or a VirtualStore redirect. Development is unaffected: under cargo run the two directories are the same. :memory: and file: URIs are left alone. - Hand the db path to sqlx as a filesystem path instead of formatting it into a sqlite:// URL, which percent-decodes it and splits it on '?'. An installed path containing %20 previously opened a different file; verified it now does not. - Create the config's and the database's parent directories when missing, so a service can name /var/lib/runicgateway on a host where nothing made it yet. - 22 unit tests covering argument parsing, path anchoring, token persistence, the generated config template, and the --print-config document. No protocol change: PROTOCOL_VERSION stays 3. Co-Authored-By: Claude <noreply@anthropic.com>
103 lines
4.7 KiB
Markdown
103 lines
4.7 KiB
Markdown
# uo-link — Rust sidecar
|
|
|
|
The **Rust sidecar** half of the Runic Gateway bridge. The ServUO shard dials out to this sidecar
|
|
over a loopback TCP socket (newline-delimited JSON); the sidecar owns the WebSocket + REST API the
|
|
website consumes, along with auth, buffering, and fan-out.
|
|
|
|
```
|
|
ServUO plugin (C#, net48) ──loopback TCP, newline-JSON──► Rust sidecar ──WebSocket/JSON──► website
|
|
(RunicGateway/servuo-plugins) >>> THIS REPO <<<
|
|
```
|
|
|
|
The shard never speaks WebSocket and exposes no port of its own — the sidecar is the only
|
|
network-facing component, which is what keeps the game unreachable from the internet.
|
|
|
|
## Related repos
|
|
|
|
| Repo | What |
|
|
|------|------|
|
|
| **this** — `RunicGateway/link` | The Rust sidecar (`sidecar/`). |
|
|
| [RunicGateway/servuo-plugins](https://gitea.whitlocktech.com/RunicGateway/servuo-plugins) | The **C# ServUO plugin** — the shard side of the bridge (`overlay/`, `patches/`, `deploy.ps1`, test scaffolding). |
|
|
| [RunicGateway/docs](https://gitea.whitlocktech.com/RunicGateway/docs) | All project documentation — design docs, protocol spec, integration guide, research. |
|
|
|
|
## Layout
|
|
|
|
| Path | What |
|
|
|------|------|
|
|
| `sidecar/` | The Rust sidecar crate — terminates the loopback link to the shard, exposes WS + REST to the website. See [`sidecar/README.md`](sidecar/README.md). |
|
|
| `.gitea/workflows/pr-checks.yml` | Gates every PR into `main` on `cargo fmt --check`, `cargo clippy -D warnings`, and `cargo test`. |
|
|
| `.gitea/workflows/release.yml` | Builds + releases the sidecar binary (Linux + Windows) on every merge to `main`. |
|
|
|
|
## Build & run
|
|
|
|
The sidecar is a standard cargo crate:
|
|
|
|
```bash
|
|
cd sidecar
|
|
cargo build --release # binary at target/release/uo-link-sidecar
|
|
cp sidecar.toml.example sidecar.toml # then edit
|
|
cargo run --release
|
|
```
|
|
|
|
Deploying it rather than developing on it: `--config <PATH>` names the config file (as does
|
|
`$UOLINK_CONFIG`), and `--print-config` prints the resolved settings — **including the auth token
|
|
the website needs** — as JSON, provisioning the config file on first run. That is the supported way
|
|
to read the token back; it is not meant to be scraped from the log.
|
|
|
|
```bash
|
|
uo-link-sidecar --print-config --config /etc/runicgateway/sidecar.toml
|
|
```
|
|
|
|
`.gitea/workflows/release.yml` cross-compiles Linux + Windows binaries and cuts a Gitea release on
|
|
every merge to `main` (conventional-commit versioning). See [`sidecar/README.md`](sidecar/README.md)
|
|
for configuration and the wire protocol.
|
|
|
|
Before that, `.gitea/workflows/pr-checks.yml` runs the same gates on every pull request into `main` —
|
|
`cargo fmt --check`, `cargo clippy --all-targets -- -D warnings`, then `cargo test --locked`. Run them
|
|
locally before pushing and the PR will be green:
|
|
|
|
```bash
|
|
cd sidecar
|
|
cargo fmt # or --check to just report
|
|
cargo clippy --locked --all-targets -- -D warnings
|
|
cargo test --locked
|
|
```
|
|
|
|
## Deployment & compatibility
|
|
|
|
The plugin ([RunicGateway/servuo-plugins](https://gitea.whitlocktech.com/RunicGateway/servuo-plugins))
|
|
and this sidecar are deployed **together** but built **independently**:
|
|
|
|
- The **plugin** is deployed as source into the ServUO server root and compiled by ServUO at boot —
|
|
no build artifact, no CI build.
|
|
- The **sidecar** is a standalone Rust binary released from this repo.
|
|
|
|
The only coupling is the **loopback JSON protocol** (the shard dials `127.0.0.1`). Compatibility is a
|
|
protocol concern, not a build-order one — keep the event/command catalog in sync across the two
|
|
repos. Canonical spec:
|
|
[PLAN.md](https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/link/PLAN.md) §5/§7 and
|
|
[INTEGRATION.md](https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/link/INTEGRATION.md).
|
|
Because a wedged or absent sidecar cannot stall the shard, either side can be deployed or restarted
|
|
independently.
|
|
|
|
---
|
|
|
|
## License
|
|
|
|
Runic Gateway is free software, licensed under the **GNU General Public License
|
|
v3.0 or later** — see [LICENSE.md](LICENSE.md).
|
|
|
|
Copyright (C) 2026 Runic Gateway
|
|
|
|
This program is free software: you can redistribute it and/or modify it under
|
|
the terms of the GNU General Public License as published by the Free Software
|
|
Foundation, either version 3 of the License, or (at your option) any later
|
|
version. It is distributed WITHOUT ANY WARRANTY; without even the implied
|
|
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
General Public License for more details.
|
|
|
|
Contributions are welcome — please read [CONTRIBUTING.md](CONTRIBUTING.md) (note
|
|
the **AI-usage disclosure** requirement) and our
|
|
[Code of Conduct](CODE_OF_CONDUCT.md). Report vulnerabilities privately per
|
|
[SECURITY.md](SECURITY.md).
|