docs(website): close phase 3 — slice 5, the fragment obligation, and the rust dry run #140

Merged
whitlocktech merged 1 commits from docs/module-close-phase3 into main 2026-08-12 04:11:14 +00:00
Member

Records the slice that closes the extraction, and adds the two documents phase 3 owed: docs/modules/uo/ and the module-rust dry run.

Pairs with Module-uo#6 and website#141.

The slice found an obligation neither repo had built

MODULE_API.md §2.8 and §6.1a settle the OpenAPI fragment in detail — a module ships one, core merges the fragments of started modules into /api/docs.json. Neither half existed, so the 72 URLs module-uo serves were in no spec at all.

§2.8 and §6.1a now record what was built, including the four things settled while building it:

  • the filename is fixed by the contract, not declared in module.json, so a module cannot point core elsewhere;
  • a module namespaces what it defines (UoShardStatus) and references core's shared schemas by core's name (Error) — the first would collide and lose, the second resolves in the merged document;
  • the generator derives its prefixes from the module's own register() call rather than a table beside it;
  • swagger-autogen's diagnostics have to be captured, because it reports a broken annotation and then prints Success.

§5.3 gains the decision the frozen manifest actually made

It is a subtraction, not a prefix filter. Generating the manifest without the module and then with it answers "what does the module serve" and "did core lose anything" — and the second is the one §1.2 promises to the shipped Android app and the Discord bot. A module that shadowed or displaced a core route cannot appear as an addition anywhere.

New: docs/modules/

Per §2.10 — module documentation aggregates here, not in module repos.

  • modules/uo/README.md orients a reader on what module-uo serves (72 URLs, per mount), what it owns (27 tables, seven streams, the public-safety filter), and what an operator needs. It links out to the feature docs that already existed rather than restating them, and defers to MODULE_API.md for anything contractual.
  • modules/rust-dryrun.md is phase 3's fourth acceptance criterion.

The dry run

A written, deliberately unimplemented module for Rust — chosen because it shares almost nothing with UO: it wipes monthly, a community runs several servers rather than one shard, its identity is Steam, and its server ships RCON so there is no sidecar to write.

The contract generalises. Same module.json, same seven registration calls, same schema-fragment rules, same client registry — and six of the UI kit's seven members wanted by a game with nothing in common with the one the kit was curated from.

It found one real gap: a module cannot register an identity provider, and "Sign in with Steam" is what a Rust community expects. A Rust module can still ship by copying UO's in-game-code flow, one screen worse. Recorded as the first candidate for a future MODULE_API_VERSION bump rather than bolted on now — an identity provider participates in session creation, which is the one part of core a module must never be able to weaken, and §2.7's link-only SSO policy has to survive it.

It also found two rules doing work they were not written for: §2.6's leading-verb allowlist (written because a fragment replays every boot) correctly forbids the wipe-truncation a Rust author would put in their schema, and capabilities — decoration with one module — is the only thing the Android app can ask about a module it has never heard of.

Also

  • BACKEND_DESIGN.md §4.0.1 is new: /api/docs.json is assembled per request; the two generated artifacts are core's alone. Its route count still said 228.
  • website-README.md refreshed from the repo — it was several changes stale.
  • Settled decisions 18–20 (manifest by subtraction, declared release version, schema namespacing).
  • MODULE_SYSTEM.md marks Phase 3 complete, with a table showing where each of the four acceptance criteria is proved.

AI-assisted contribution. Written with Claude Code (Claude Opus). Commits carry Co-Authored-By: Claude <noreply@anthropic.com>.

🤖 Generated with Claude Code

Records the slice that closes the extraction, and adds the two documents phase 3 owed: `docs/modules/uo/` and the `module-rust` dry run. Pairs with **Module-uo#6** and **website#141**. ## The slice found an obligation neither repo had built `MODULE_API.md` §2.8 and §6.1a settle the OpenAPI fragment in detail — a module ships one, core merges the fragments of started modules into `/api/docs.json`. **Neither half existed**, so the 72 URLs module-uo serves were in no spec at all. §2.8 and §6.1a now record what was built, including the four things settled while building it: - the filename is **fixed by the contract**, not declared in `module.json`, so a module cannot point core elsewhere; - a module **namespaces what it defines** (`UoShardStatus`) and **references core's shared schemas by core's name** (`Error`) — the first would collide and lose, the second resolves in the merged document; - the generator **derives its prefixes** from the module's own `register()` call rather than a table beside it; - swagger-autogen's diagnostics **have to be captured**, because it reports a broken annotation and then prints `Success`. ## §5.3 gains the decision the frozen manifest actually made It is a **subtraction, not a prefix filter**. Generating the manifest without the module and then with it answers "what does the module serve" *and* "did core lose anything" — and the second is the one §1.2 promises to the shipped Android app and the Discord bot. A module that shadowed or displaced a core route cannot appear as an addition anywhere. ## New: `docs/modules/` Per §2.10 — module documentation aggregates here, not in module repos. - **[`modules/uo/README.md`](modules/uo/README.md)** orients a reader on what module-uo serves (72 URLs, per mount), what it owns (27 tables, seven streams, the public-safety filter), and what an operator needs. It links out to the feature docs that already existed rather than restating them, and defers to `MODULE_API.md` for anything contractual. - **[`modules/rust-dryrun.md`](modules/rust-dryrun.md)** is phase 3's fourth acceptance criterion. ## The dry run A written, deliberately unimplemented module for **Rust** — chosen because it shares almost nothing with UO: it **wipes** monthly, a community runs several **servers** rather than one shard, its identity is **Steam**, and its server ships **RCON** so there is no sidecar to write. **The contract generalises.** Same `module.json`, same seven registration calls, same schema-fragment rules, same client registry — and **six of the UI kit's seven members** wanted by a game with nothing in common with the one the kit was curated from. It found one real gap: **a module cannot register an identity provider**, and "Sign in with Steam" is what a Rust community expects. A Rust module can still ship by copying UO's in-game-code flow, one screen worse. Recorded as the first candidate for a future `MODULE_API_VERSION` bump rather than bolted on now — an identity provider participates in session creation, which is the one part of core a module must never be able to weaken, and §2.7's link-only SSO policy has to survive it. It also found two rules doing work they were not written for: §2.6's leading-verb allowlist (written because a fragment replays every boot) correctly forbids the wipe-truncation a Rust author would put in their schema, and `capabilities` — decoration with one module — is the only thing the Android app can ask about a module it has never heard of. ## Also - **`BACKEND_DESIGN.md` §4.0.1** is new: `/api/docs.json` is assembled per request; the two generated artifacts are core's alone. Its route count still said 228. - `website-README.md` refreshed from the repo — it was several changes stale. - Settled decisions 18–20 (manifest by subtraction, declared release version, schema namespacing). - `MODULE_SYSTEM.md` marks **Phase 3 complete**, with a table showing where each of the four acceptance criteria is proved. --- **AI-assisted contribution.** Written with Claude Code (Claude Opus). Commits carry `Co-Authored-By: Claude <noreply@anthropic.com>`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
wtclaude added 1 commit 2026-08-12 04:06:29 +00:00
Records the slice that closes the extraction, and adds the two documents phase 3
owed: docs/modules/uo/ and the module-rust dry run.

**The slice found an obligation neither repo had built.** MODULE_API.md §2.8 and
§6.1a settle the OpenAPI fragment in detail — a module ships one, core merges the
fragments of started modules into /api/docs.json. Neither half existed, so the 72
URLs module-uo serves were in no spec at all. §2.8 and §6.1a now record what was
built, including the four things settled while building it: the filename is fixed
rather than declared, a module namespaces what it DEFINES and references core's
shared schemas by core's name, the generator derives its prefixes from the
module's own register() call, and swagger-autogen's diagnostics have to be
captured because it reports a broken annotation and then prints Success.

**§5.3 gains the design decision the frozen manifest actually made:** it is a
SUBTRACTION, not a prefix filter. Generating the manifest without the module and
then with it answers "what does the module serve" AND "did core lose anything",
and the second is the one §1.2 promises to the shipped Android app. A module that
shadowed a core route cannot appear as an addition anywhere.

**BACKEND_DESIGN.md §4.0.1** is new: /api/docs.json is assembled per request, the
two generated artifacts are core's alone, and the route count was still 228.

**docs/modules/** is new, per §2.10 (module documentation aggregates here, not in
module repos): docs/modules/uo/README.md orients a reader on what module-uo
serves, owns and needs from an operator, and links out to the feature docs that
already existed rather than restating them.

**docs/modules/rust-dryrun.md** is phase 3's fourth acceptance criterion. A
written, deliberately unimplemented module for Rust — chosen because it wipes
monthly, runs several servers rather than one shard, identifies by Steam, and
ships RCON so there is no sidecar to write. The contract generalises: same
manifest, same seven registration calls, same schema rules, and six of the UI
kit's seven members wanted by a game with nothing in common with the one the kit
was curated from.

It found one real gap — **a module cannot register an identity provider**, and
"Sign in with Steam" is what a Rust community expects. Recorded as the first
candidate for a future MODULE_API_VERSION bump rather than bolted on: an identity
provider participates in session creation, and §2.7's link-only SSO policy has to
survive it.

Also: website-README.md refreshed from the repo (it was several changes stale),
and three settled decisions added (18-20).

Pairs with Module-uo#6 and website#141.

Co-Authored-By: Claude <noreply@anthropic.com>
whitlocktech merged commit d171253715 into main 2026-08-12 04:11:14 +00:00
whitlocktech deleted branch docs/module-close-phase3 2026-08-12 04:11:17 +00:00
Sign in to join this conversation.
No description provided.