feat(sidecar)!: bump PROTOCOL_VERSION to 3

Protocol 3.0 is feature-complete on `edge` -- world.ruleset, points.board and
vendor.listing / vendor.listing.remove all landed there while the sidecar kept
declaring 2, because a bump is an operator-visible hard break (409 on every
protected route via web.rs::gate, and the website closes the WS on the ws.hello
mismatch). Doing it per phase would have broken the site four times; this is the
one time it happens.

Nothing that existed in v2 changed shape, so the version constant and its doc
comment are the whole change here. The README's worked example moves with it --
it still claimed "currently 1", two bumps stale.

Verified against the release binary: /health reports "protocol": 3, every
response carries `X-UOLink-Version: 3`, an authenticated request declaring 2 is
refused 409 {"sidecar_protocol":3,"client_protocol":"2"}, and one declaring 3
gets 200 off /ruleset. cargo build --release + cargo clippy --all-targets clean.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-07-29 18:03:31 -05:00
parent 05e192ca70
commit 5f50b881ca
2 changed files with 9 additions and 4 deletions

View File

@@ -41,10 +41,10 @@ So you can never accidentally run without auth. Rotate by editing the token and
## Protocol version
The wire protocol has a version (`PROTOCOL_VERSION`, currently **1**), so the website and sidecar detect a mismatch immediately instead of failing in strange ways when a message shape changes.
The wire protocol has a version (`PROTOCOL_VERSION`, currently **3**), so the website and sidecar detect a mismatch immediately instead of failing in strange ways when a message shape changes.
- Every response carries an `X-UOLink-Version: 1` header.
- `/health` and the WebSocket `ws.hello` include `"protocol": 1`.
- Every response carries an `X-UOLink-Version: 3` header.
- `/health` and the WebSocket `ws.hello` include `"protocol": 3`.
- If a request sends `X-UOLink-Version` and it disagrees with the sidecar, the request is rejected **409 Conflict** with `{sidecar_protocol, client_protocol}` so the mismatch is obvious.
Bump `PROTOCOL_VERSION` in `main.rs` whenever an event or endpoint's shape changes.

View File

@@ -24,7 +24,12 @@ use tracing_subscriber::EnvFilter;
/// v2 (Protocol 2.0): adds the account-provisioning verbs/endpoints (`POST /accounts/create`,
/// `DELETE /link/:account`) and their events. Outbound event kinds are additive, so a v1 website
/// keeps working against the live feed; the new *endpoints* require a v2 sidecar.
pub const PROTOCOL_VERSION: u32 = 2;
///
/// v3 (Protocol 3.0): adds `world.ruleset`, `points.board` and `vendor.listing` /
/// `vendor.listing.remove`, with the `GET /ruleset`, `/points` and `/market` reads that serve them
/// from the store. Same shape as the v2 bump — the kinds are additive, the endpoints are not — and
/// there is deliberately no feature-negotiation array: v3 implies all three kinds.
pub const PROTOCOL_VERSION: u32 = 3;
#[tokio::main]
async fn main() -> anyhow::Result<()> {