docs(modules): the Rust dry run, revisited for Teams #167

Merged
whitlocktech merged 1 commits from docs/rust-dryrun-teams into edge 2026-08-19 08:53:56 +00:00
Member

A phase 11 rider. The integration kit's README sends a reader here first"the shortest honest picture of the whole job" — and it predated Teams, so it taught a second game to build its teams as private module data and never mentioned registerTeamProvider.

The two places the contract changed since it was written are now in it. Nothing else moved, and all four findings stand — the identity gap (Steam OpenID) is still open and still the one a real second module hits first.

What Rust adds that UO does not

Revisiting rather than annotating was worth it, because Rust makes the provider's rules bite harder:

  • externalId must survive a rename, and a Rust team has no name — it is a numeric team id in the server's save. The right answer, and the one a designer is least likely to reach for.
  • complete is per SERVER, not per community. A community running six servers has six team spaces, so a provider that can reach five must leave complete off or core archives every Team on the sixth.
  • A wipe empties every team, so { ok: true, complete: true, teams: [] } is true once a month and core archiving all of them is correct — which is exactly why an unreachable RCON must answer { ok: false } instead. The two states are one API call apart and only the module can tell them apart.
  • The team route carries a server id as well as a team id, so the external id is <serverId>:<teamId>. Core stores that string and never parses it; an external id is opaque to core by design, and this is the case that shows why.

Also: rust_teams stays the module's table and core's teams stays core's — the boundary is worth stating in the one document where both appear — and the UI kit is nine members now, not seven.

AI disclosure

Written with Claude Code (Opus 5). Commits carry the Co-Authored-By trailer.

A phase 11 rider. The integration kit's README sends a reader **here first** — *"the shortest honest picture of the whole job"* — and it predated Teams, so it taught a second game to build its teams as private module data and never mentioned `registerTeamProvider`. The two places the contract changed since it was written are now in it. **Nothing else moved**, and all four findings stand — the identity gap (Steam OpenID) is still open and still the one a real second module hits first. ### What Rust adds that UO does not Revisiting rather than annotating was worth it, because Rust makes the provider's rules bite harder: - **`externalId` must survive a rename, and a Rust team has no name** — it is a numeric team id in the server's save. The right answer, and the one a designer is least likely to reach for. - **`complete` is per SERVER, not per community.** A community running six servers has six team spaces, so a provider that can reach five must leave `complete` off or core archives every Team on the sixth. - **A wipe empties every team**, so `{ ok: true, complete: true, teams: [] }` is *true* once a month and core archiving all of them is *correct* — which is exactly why an unreachable RCON must answer `{ ok: false }` instead. The two states are one API call apart and only the module can tell them apart. - **The team route carries a server id as well as a team id**, so the external id is `<serverId>:<teamId>`. Core stores that string and never parses it; an external id is opaque to core by design, and this is the case that shows why. Also: `rust_teams` stays the module's table and core's `teams` stays core's — the boundary is worth stating in the one document where both appear — and the UI kit is nine members now, not seven. ### AI disclosure Written with Claude Code (Opus 5). Commits carry the `Co-Authored-By` trailer.
wtclaude added 1 commit 2026-08-19 08:51:28 +00:00
The kit's README sends a reader here FIRST - it is the shortest honest picture of
the whole job - and it predated Teams, so it taught a second game to build its
teams as private module data and never mentioned the provider. The two places the
contract changed since it was written are now in it, and nothing else moved:
all four findings stand, including the identity gap, which is still the one a
real second module hits first.

What Rust adds that UO does not, and why it was worth revisiting rather than
noting:

- externalId must survive a rename and a Rust team HAS no name - it is a numeric
  team id in the save. The right answer, and the one a designer is least likely
  to reach for.
- `complete` is per SERVER, not per community. Six servers are six team spaces,
  so a provider that can reach five must leave `complete` off or core archives
  every team on the sixth.
- A wipe empties every team, so { ok: true, complete: true, teams: [] } is TRUE
  once a month and core archiving all of them is correct - which is exactly why
  an unreachable RCON must answer { ok: false } instead. The two states are one
  API call apart and only the module can tell them apart.
- The team route carries a server id as well as a team id, so the external id is
  <serverId>:<teamId>. Core stores that and never parses it; an external id is
  opaque to core by design, and this is the case that shows why.

Also: rust_teams stays the module's table and core's teams stays core's, which is
the boundary worth stating in the one document where both appear; and the kit is
nine members now, not seven.

Co-Authored-By: Claude <noreply@anthropic.com>
whitlocktech merged commit 508e738527 into edge 2026-08-19 08:53:56 +00:00
whitlocktech deleted branch docs/rust-dryrun-teams 2026-08-19 08:53:58 +00:00
Sign in to join this conversation.
No description provided.