wtclaude 680a4866ac docs(teams): Team core, MODULE_API 1.6.0, and what phase 2 disproved
Documents phase 2 of docs/website/TEAMS.md across the three files that had to
change, and records the five places building it disagreed with the design.

## MODULE_API.md — 1.6.0

The Team surface becomes contract: `api.registerTeamProvider(...)`,
`ctx.teams.publish` / `ctx.teams.reconcile` / `ctx.teams.activity.push`,
`api.registerSlashCommands(...)`, and the two client slots. Additions only, so
minor; module-uo's `coreApi: "^1.3.0"` still resolves.

Per the org lead's decision, one 1.6.0 covers the whole surface rather than a
minor per phase -- so the document names the phase against each member, and the
two that cannot work yet are marked as present-and-throwing rather than left to
be discovered at runtime.

`registerTeamProvider` gets the fullest treatment because it is the first
registration where core calls the MODULE and waits for an answer. The envelope,
the 10-second budget and the refusal semantics are all contract, not
implementation: they are how a module says "I cannot answer" without core hearing
"there is nothing". `ctx.teams` is documented as push-only, with the reason there
is no reader — a module answers questions about Teams, it does not ask them.

## BACKEND_DESIGN.md

The six Team tables, the rename rule, the active-only uniqueness encoding, the
per-column account-deletion decisions, and all eighteen routes across the three
tier tables.

Two entries there exist to stop a future reader "fixing" them: why
`team_forum_grants` does not use the obvious generated column, and why the two
columns TEAMS.md never mentioned have to exist.

## TEAMS.md — five amendments, marked as amendments with their date

  - **§2.5's SQL and §2.10's decision cannot both hold.** MariaDB refuses ON
    DELETE SET NULL on a base column of a stored generated column (1901), so
    §2.5's `active_user` forces the CASCADE that §2.10 exists to prevent. §2.10
    wins; the marker is re-encoded for identical semantics.

  - **`team_forum_grants` lands in phase 2**, so the four-path resolver is written
    once and its non-contamination tests are real.

  - **Two columns the document did not contemplate**, both serving §2.4's gates:
    `roster_synced_at`, because sync state is per MODULE and gate 3 leaves one
    Team behind while the others sync; and `members_empty_since`, gate 4's
    per-Team quarantine.

  - **`leader` on the member shape is not path 2.** Taking §2.3 and §2.5 both
    literally gives one column two writers, and the roster writes first — so a
    refused `getTeamLeaders()` silently demoted everyone. Found by its own test.

  - **§2.8.2's matcher needed two narrow widenings**, both real impersonation
    vectors the whole-word rule missed: a term matches a name word's singular
    ("Guild of Moderators"), and a run of single-letter words is compared joined
    ("G.M."). Neither re-admits substring matching.

Pairs with website (Teams phase 2) and Module-uo (the provider).

Refs docs/website/TEAMS.md Part 12 phase 2

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-17 15:32:21 -05:00

Runic Gateway — Documentation

Central documentation for the Runic Gateway platform. The docs here were extracted from the two code repositories (with full commit history preserved) so they live in one place, independent of either codebase.

Layout

website/    docs from the website core (Node/Express + MariaDB + React/Vite)
modules/    docs for installable game modules — one directory per module id
link/       docs from the ServUO bridge (C# plugin + Rust sidecar + Node WS)
android/    docs from the native Android client (Kotlin + Jetpack Compose)
installer/  docs for the installer that deploys a shard's bridge components
ci/         cross-cutting CI/quality notes

Setting up a shard? installer/INSTALL.md is the operator guide, and the installer is the supported path: one binary deploys the plugin overlay, installs the uo-link sidecar as a service, and hands you the values the website needs.

website/

Doc What it covers
BACKEND_DESIGN.md API contract, DB schema, security model
HERO_EDITOR.md Hero canvas editor feature spec
THEMING_AND_NAV.md Admin-configurable theme, brand assets and navigation — build contract
MODULE_SYSTEM.md Making the site game-agnostic: game logic becomes an installable module — design of record
MODULE_API.md The module ↔ core contract: ctx, the register* calls, the client registry and the loader's obligations
WIKI_UPGRADE.md Wiki subsystem upgrade notes
SHARD_VISIBILITY.md Who sees which shard data — the admin-configurable audience framework
SPAWN_ATLAS.md The bestiary / spawn atlas: what the shard contains, parsed from its own ServUO tree
CLILOCS.md UO's id → name table: converting one from your client so items have names
UOFIDDLER.md Operator runbook — step-by-step extraction from your own UO client (cliloc table, creature art)
MARKETPLACE.md The player-vendor index: how it is gathered, what it costs, how to tune it
website-README.md Snapshot of the website repo's README (setup/run reference)
PROJECT_TREE.md Auto-generated snapshot of the repo's tracked file layout

modules/

Documentation for installable game modules aggregates here rather than in each module's repo (MODULE_SYSTEM.md §2.10). The website core knows nothing about any particular game; a module is what makes it a site for one.

Doc What it covers
uo/ module-uo — the Ultima Online module: what it serves, what it owns, and what an operator needs
rust-dryrun.md A written, deliberately unimplemented module-rust — the test that the module contract generalises past the game it was extracted from
Doc What it covers
INTEGRATION.md How the website integrates with the uo-link sidecar
PROTOCOL_2.md Protocol 2.0 / 2.1 design
v3.md Protocol 3.0 design — shard content/standings streams + the visibility framework
ADMIN_CONTROLS.md Staff write-plane (kick/ban/broadcast, page queue)
SHARD_PREREQS.md Shard-side prerequisites for the bridge
PLAN.md uo-link build plan
RESEARCH.md Research notes
link-README.md Snapshot of the link repo's README
PROJECT_TREE.md Auto-generated snapshot of the repo's tracked file layout

android/

Doc What it covers
PLAN.md Android client build plan / milestones
COVERAGE_PLAN.md Test-coverage rollout plan
APP_LINKS.md Android App Links / deep-link setup
theme-plan.md Theming plan
TRUSTED_DEVICES_APP_HANDOFF.md Trusted-devices app handoff notes
PROJECT_TREE.md Auto-generated snapshot of the repo's tracked file layout

installer/

Doc What it covers
INSTALL.md Start here to set up a shard — the installer deploys the plugin overlay and the uo-link sidecar, registers the service, and connects it to the website. Appendix A is the same thing by hand, still supported
PLAN.md Installer design of record — phases, locked decisions, the bundle/compat-matrix model

Provenance

  • website/* was extracted from RunicGateway/website via git filter-repo.
  • link/* was extracted from RunicGateway/link via git filter-repo.

Commit history and authorship for each doc are preserved. The two source repos retain a short pointer to this repo in their own READMEs; the authoritative copy of each document now lives here.


License

Runic Gateway's documentation is free: licensed under the GNU General Public License v3.0 or later — see LICENSE.md.

Copyright (C) 2026 Runic Gateway

This documentation is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY. You may redistribute and/or modify it under the terms of
the GNU General Public License as published by the Free Software Foundation,
either version 3 of the License, or (at your option) any later version.

Contributions are welcome — please read CONTRIBUTING.md (note the AI-usage disclosure requirement) and our Code of Conduct.

Description
No description provided
Readme 23 MiB
Languages
Markdown 100%