feat(sidecar): protocol 4 — two routes, and no opinion about either
All checks were successful
PR Checks / rust-gates (pull_request) Successful in 1m38s
All checks were successful
PR Checks / rust-gates (pull_request) Successful in 1m38s
`GET /permissions/catalogue` and `POST /permissions/sync` (R2). The first pair that exists so the website can WRITE to the game, and the smallest change in this repository that a protocol bump has ever needed. That is the dumb-forwarder property paying for itself a second time: protocol 4 adds the largest command on the bridge and touches neither the store nor the feed. The sidecar does not know what a group is, which names are managed, or what the plugin will do with any of it. It puts an envelope on an object and forwards it. **The envelope is this side's.** `cmd` and `reqId` are inserted AFTER the caller's object is taken, so they overwrite anything a caller put there — no request can arrive claiming to be a different command, or aimed at a correlation id somebody else is waiting on. **A command larger than the game link's line cap is refused here**, with the limit in the body. Forwarded, it would be discarded silently by both ends (§3.1 — an over-long line is dropped, not buffered) and present to the caller as a `504`, which sends an operator to look at a game server that is working perfectly. Two tests, and both assert a refusal rather than a happy path. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PMH6bw1jXMgbyF3ZWGEzSM
This commit is contained in:
@@ -71,9 +71,28 @@ use tracing_subscriber::EnvFilter;
|
||||
/// * **`GET /feed`** is the ingest cursor, oldest-first, separate from `/events` so that no
|
||||
/// caller can get the other ordering by forgetting a parameter.
|
||||
///
|
||||
/// `docs/rust-link/PROTOCOL.md` §8 is the specification; this constant is one of its four
|
||||
/// declaration sites.
|
||||
pub const PROTOCOL_VERSION: u32 = 3;
|
||||
/// # Protocol 3 — identity
|
||||
///
|
||||
/// `POST /link/confirm`, the first route here that is not a GET, and the first message on this
|
||||
/// bridge the WEBSITE originates. It forwards a six-character code to the plugin and hands back
|
||||
/// what the plugin said. The codes live in the game's memory and nowhere else: putting the table
|
||||
/// here would give this process a credential and an opinion, and it is designed to have neither.
|
||||
///
|
||||
/// # Protocol 4 — the permission mirror
|
||||
///
|
||||
/// `GET /permissions/catalogue` and `POST /permissions/sync` (R2). The first command that WRITES
|
||||
/// to the game: the website sends the whole permission set it authors for this server and the
|
||||
/// plugin reconciles the store against it.
|
||||
///
|
||||
/// Nothing about that shape is visible in this process beyond two routes, and that is the
|
||||
/// dumb-forwarder property paying for itself a second time — protocol 4 adds the largest command
|
||||
/// on the bridge and touches neither the store nor the feed. The one thing this side owns is the
|
||||
/// envelope: `cmd` and `reqId` are written over whatever the caller sent, and a command that would
|
||||
/// not fit on the game link is refused here rather than discarded silently at the other end.
|
||||
///
|
||||
/// `docs/rust-link/PROTOCOL.md` is the specification — §8 the read path, §9 identity, §10 the
|
||||
/// mirror; this constant is one of its four declaration sites.
|
||||
pub const PROTOCOL_VERSION: u32 = 4;
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let args = match cli::parse(std::env::args().skip(1)) {
|
||||
|
||||
Reference in New Issue
Block a user