fix(uo-link): pin protocol 4, the version this build actually speaks #20

Merged
whitlocktech merged 1 commits from fix/protocol-4-pin into main 2026-08-25 00:33:46 +00:00
Member

What was wrong

The protocol-4 cutover moved link's PROTOCOL_VERSION, the overlay's overlay.toml and this module's ingestguild.roster and guild.leave landed with the Teams cutover — but left this module's two pin sites at 3:

  • DEFAULT_PROTOCOL in server/model/uoLinkConfig/uoLinkConfig.model.js
  • the uo_link_config.protocol column default in server/db/schema.sql

A fresh install therefore came up speaking 3 to a protocol-4 sidecar. A sidecar answers a stale client 409 protocol version mismatch rather than mis-parsing it, so the failure is total and quiet: every REST read fails, the WS closes on ws.hello, and the operator sees an empty marketplace, an empty guild board and no shard status, with the cause visible only in the server log.

ERROR [uo:uo-link-client] uo-link protocol mismatch (409)
  {"path":"/guilds","body":{"client_protocol":"3","sidecar_protocol":4}}

It cleared only when an admin edited the number by hand in Admin → Shard.

Existing installs were unaffected, which is why this went unnoticed — the protocol-3 one-shot had already moved their stored row, and the stored row wins. It bites exactly the path the installer makes the supported one: a new deployment.

Found while standing up a demo deployment for the marketing site's screenshots (runicgateway.com phase 9).

The fix

  • DEFAULT_PROTOCOL → 4, with the reason recorded where the constant lives.
  • The column default → 4 at both declaration sites.
  • A protocol-4 one-shot mirroring the protocol-3 one: guarded by its own marker in settings so an operator who deliberately pins an older sidecar in Admin → Shard stays pinned, and written protocol < 4 rather than = 3 so an install that never took the protocol-3 migration is carried the whole way rather than one step. The marker is written after the UPDATE that reads it, and in this module's fragment rather than core's — the lesson the protocol-3 block already records.

Tests

Three regressions in server/test/schemaFragment.test.js, all failing against the old file:

  • the CREATE TABLE default and the last MODIFY both name the protocol this build speaks
  • the protocol-4 marker is written after the UPDATE that reads it
  • the one-shot uses protocol < 4, so any older pin is carried forward

npm test --prefix server → 453 pass, 0 fail.

Verified live

Against the real stack on this machine — ServUO + protocol-4 sidecar + core with this module installed. Before: 409 on /guilds, /market, /towncrier, everything. After pointing the config at protocol 4: guild board, governors, houses, points boards, ruleset and the 27-vendor market all snapshot on connect.

Docs half: docs PR — v4's cross-repo obligation table named only the ingest work, and that omission is what let this through. A protocol bump owes four declaration sites, not three.


  • AI-assisted: written with Claude Code (Claude Opus).

Co-Authored-By: Claude <noreply@anthropic.com>

## What was wrong The protocol-4 cutover moved `link`'s `PROTOCOL_VERSION`, the overlay's `overlay.toml` and **this module's ingest** — `guild.roster` and `guild.leave` landed with the Teams cutover — but left this module's two *pin* sites at 3: - `DEFAULT_PROTOCOL` in `server/model/uoLinkConfig/uoLinkConfig.model.js` - the `uo_link_config.protocol` column default in `server/db/schema.sql` A fresh install therefore came up speaking 3 to a protocol-4 sidecar. A sidecar answers a stale client `409 protocol version mismatch` rather than mis-parsing it, so the failure is total and quiet: **every** REST read fails, the WS closes on `ws.hello`, and the operator sees an empty marketplace, an empty guild board and no shard status, with the cause visible only in the server log. ``` ERROR [uo:uo-link-client] uo-link protocol mismatch (409) {"path":"/guilds","body":{"client_protocol":"3","sidecar_protocol":4}} ``` It cleared only when an admin edited the number by hand in Admin → Shard. **Existing installs were unaffected**, which is why this went unnoticed — the protocol-3 one-shot had already moved their stored row, and the stored row wins. It bites exactly the path the installer makes the supported one: a new deployment. Found while standing up a demo deployment for the marketing site's screenshots (runicgateway.com phase 9). ## The fix - `DEFAULT_PROTOCOL` → 4, with the reason recorded where the constant lives. - The column default → 4 at both declaration sites. - A protocol-4 one-shot mirroring the protocol-3 one: guarded by its own marker in `settings` so an operator who deliberately pins an older sidecar in Admin → Shard **stays pinned**, and written `protocol < 4` rather than `= 3` so an install that never took the protocol-3 migration is carried the whole way rather than one step. The marker is written *after* the UPDATE that reads it, and in this module's fragment rather than core's — the lesson the protocol-3 block already records. ## Tests Three regressions in `server/test/schemaFragment.test.js`, all failing against the old file: - the `CREATE TABLE` default and the last `MODIFY` both name the protocol this build speaks - the protocol-4 marker is written after the UPDATE that reads it - the one-shot uses `protocol < 4`, so any older pin is carried forward `npm test --prefix server` → 453 pass, 0 fail. ## Verified live Against the real stack on this machine — ServUO + protocol-4 sidecar + core with this module installed. Before: `409` on `/guilds`, `/market`, `/towncrier`, everything. After pointing the config at protocol 4: guild board, governors, houses, points boards, ruleset and the 27-vendor market all snapshot on connect. Docs half: `docs` PR — v4's cross-repo obligation table named only the ingest work, and that omission is what let this through. A protocol bump owes **four** declaration sites, not three. --- - [x] AI-assisted: written with Claude Code (Claude Opus). Co-Authored-By: Claude &lt;noreply@anthropic.com&gt;
wtclaude added 1 commit 2026-08-25 00:23:57 +00:00
fix(uo-link): pin protocol 4, the version this build actually speaks
All checks were successful
PR Checks / client-build (pull_request) Successful in 24s
PR Checks / server-tests (pull_request) Successful in 28s
PR Checks / frozen-manifest (pull_request) Successful in 40s
7f7d4578ce
The protocol-4 cutover moved `link`'s PROTOCOL_VERSION, the overlay's
`overlay.toml` and this module's ingest — `guild.roster` and `guild.leave`
landed with the Teams cutover — but left both of this module's pin sites at 3.

A fresh install therefore came up speaking 3 to a protocol-4 sidecar, and a
sidecar answers a stale client with `409 protocol version mismatch` rather than
mis-parsing it. The failure is total and silent: every REST read fails, the WS
closes on ws.hello, and the operator sees an empty marketplace, an empty guild
board and no shard status, with the cause only in the server log. It cleared
only when an admin edited the number by hand in Admin → Shard.

Found while standing up a demo deployment for the marketing site's screenshots.

- `DEFAULT_PROTOCOL` → 4 (the constant used before an admin has saved anything)
- the `uo_link_config.protocol` column default → 4, at both declaration sites
- a protocol-4 one-shot mirroring the protocol-3 one, guarded by its own marker
  so an operator who deliberately pins an older sidecar stays pinned, and
  written `protocol < 4` so an install that never took the protocol-3 migration
  is carried the whole way rather than one step
- three regression tests: the column default, the marker ordering, and the
  `< 4` predicate

Co-Authored-By: Claude <noreply@anthropic.com>
whitlocktech approved these changes 2026-08-25 00:33:39 +00:00
whitlocktech merged commit 1b6d92a5ba into main 2026-08-25 00:33:46 +00:00
whitlocktech deleted branch fix/protocol-4-pin 2026-08-25 00:33:47 +00:00
Sign in to join this conversation.
No Reviewers
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: RunicGateway/Module-uo#20
No description provided.