Files
Rust-Plugins/overlay.toml
wtclaude 48eeb56300
All checks were successful
PR Checks / plugin-checks (pull_request) Successful in 10s
feat(bridge): protocol 5 — configuration from the site, and the reload that undoes itself
R18. Three request/reply verbs — `config.list`, `config.read`, `config.write` —
and the first command on this bridge that writes to the game host's filesystem.

The walk is rooted at `Interface.Oxide.ConfigDirectory`, never a literal, so it
is right on Oxide, on Carbon and on a server whose operator moved it; the data
directory is never walked, because it holds live state and both frameworks'
permission stores, which is protocol 4's mirror one directory over.

A write is resolved, version-checked and parse-checked before the first byte
lands, then backed up, written and reloaded — and the reload is WATCHED. If
`OnPluginLoaded` does not arrive within four seconds the whole set is restored,
reloaded again, and reported with the tail of the newest log file. Without that
this is a web form that takes a required plugin off a production server one typo
at a time.

Four seconds is arithmetic, not taste: the worst path is two windows while a
caller holds the sidecar's ten-second RPC budget.

This plugin will not reload itself — the reload would close the link carrying
the answer — and the site composes the file's bytes, so nothing here has an
opinion about content beyond "it parses".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PMH6bw1jXMgbyF3ZWGEzSM
2026-09-22 08:53:45 -05:00

51 lines
2.8 KiB
TOML

# Release metadata for the deployable overlay.
#
# Consumed by the release workflow, which folds these values into the
# manifest.json shipped inside the overlay tarball. The Runic Gateway installer
# reads that manifest to decide what it is deploying and whether it is compatible
# with the sidecar it is about to install.
#
# There is deliberately NO version key here. The release version is derived from
# git tags and conventional commits by the release workflow, so there is no bump
# commit to keep in sync and no way for this file to disagree with the tag.
# ── The loopback wire-protocol version this overlay speaks ───────────────────
#
# The plugin half of the compatibility contract. It MUST equal the sidecar's
# PROTOCOL_VERSION (Rust-Link's sidecar/src/main.rs) for a deployment to work:
# the sidecar rejects a mismatched WEBSITE with 409, and a mismatched PLUGIN is
# worse, because the game link has no such check — it would simply mis-parse.
#
# That asymmetry is why this file exists. The plugin announces its protocol in
# `server.hello`, which is only readable after the game server has booted with it
# loaded — far too late for an installer to refuse a bad pairing. This
# declaration is what lets the bundle CI check the pair BEFORE an operator
# installs either half.
#
# Keeping it honest is a manual duty: when the protocol changes, bump it here in
# the same change that alters the emitters, exactly as the sidecar bumps
# PROTOCOL_VERSION and the module bumps its own constant.
#
# Current: 5 — the transport, the read path, identity, the permission mirror, and
# configuration from the site (docs/rust-link/PROTOCOL.md §11).
protocol = 5
# ── Oxide compatibility ──────────────────────────────────────────────────────
#
# The overlay only ADDS a file — one plugin into `oxide/plugins/` — and patches
# nothing, so it is expected to work on any reasonably current Oxide. This is the
# oldest build it is known good on.
#
# There is no `patches_verified_against` key, and there is no `patches/` tier:
# Rust's server is a binary and Oxide's hook API is the supported way in, so
# there is nothing to diff against. That is the whole reason the Rust payload is
# simpler than the ServUO one.
min_oxide_version = "2.0.7585"
# The `oxide/plugins/` files this overlay expects to find already installed. They
# are not shipped here — they are third-party plugins an operator installs from
# uMod — and the installer's `doctor` reports a missing one rather than
# installing it. Listing them is what turns "the site shows no clans" into a
# named prerequisite.
requires_plugins = ["Clans", "Kits", "PopupNotifications", "ZoneManager"]