docs(modules): phase 2 as built — packaging, release and the frozen manifest #254

Merged
whitlocktech merged 1 commits from docs/rust-phase-2 into main 2026-09-16 10:51:03 +00:00
Member

modules/rust/PLAN.md gains §15, and the phase-2 row is marked done. Pairs with Module-Rust#2 (merged) and release v0.1.0.

The criterion is met

An operator installs the empty module from Admin → Modules and it reaches started.

Walked as an operator would, with the phase-1 state torn down first — the hand-copied modules/rust/ directory moved aside and its installed_modules row deleted — so this was a first install, not an upgrade. GET /api/v1/public/rust/servers answered 404 before it.

Paste the manifest URL → "Installed Rust v0.1.0. Restart to load it." → restart → module "rust" started. The row now carries state = started, the source URL and sha256 7296c76b988c…, where phase 1's had nulls in both, because a directory somebody copied has no provenance to record.

Three checks that it is serving and not merely loaded: the public route answers 200, the player and admin tiers answer 401 (tier gates on, not bypassed), and all five /rust paths appear in /api/docs.json — the fragment merged into core's own spec.

The volume received exactly the twenty files the include list names. No tests, no server/scripts/, no ci/, no client/src/, no node_modules, no dotfiles.

What the phase found

The starting position was worse than the row implied. Phase 1 built five guards and ran every one by hand, because the repo had no .gitea/workflows/ at all — nothing gated the branch that gets released, and there was no way to release it. Hence D4: the phase covers the gate as well as the release.

The frozen manifest answers a question §13 had to take on trust. §13's own registration comment says /rust was "checked against core's mount tables rather than assumed" — and names the limit: core mounts several public routes at a tier root (/status, /version) that the loader's collision probe cannot see. The job diffs a real core's route table with and without the module. Locally and then in CI, against the same pinned ref, agreeing exactly:

route manifest up to date (280 routes)
wrote routes.manifest.json (282 public + 4 internal)
routes.manifest.json is current — 6 routes, all documented

The bundle carries no node_modules (D5), and the emptiness is asserted rather than assumed — the point of the decision is that the day it stops being true is a loud day. Verified by breaking the include list, which names the exact edit.

REGISTRY_TOKEN was already configured. That was the one prerequisite this work could not check for itself — the bot identity can read neither repo nor org Actions secrets. The credential check exists because the answer was unknowable from here, and the first release ran clean through it.

Two things §15 is honest about

  • The Restart the server button was not exercised; the restart was done from the shell. That button needs a supervisor to bring the process back, which the shipped docker-compose.yml provides and a bare npm start does not — and it is core's behaviour, not this module's.
  • The module's two tables were left in place when the row was deleted, so the rig's main server row survived the reinstall. The schema fragment replayed on boot (statements: 2), exactly as R12 requires of a fragment that runs every time.

One rig finding, not a module finding

Docker Desktop's Linux engine was found dead — WSL distro stopped, uomm-db exited, and docker answering every call with a bare 500 Internal Server Error naming nothing. Recorded because it presents as the website being broken, and CLAUDE.md points every smoketest at that one container.

Noticed, not changed

modules/rust/README.md still describes CARBON.md as "not yet proven on a live Carbon server". §14.5 of PLAN.md disproves that — R19 was proven on Carbon 2.0.259.0. It is outside this phase's scope so I have left it; worth a one-line fix whenever someone is next in that file.

🤖 Generated with Claude Code

https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4

`modules/rust/PLAN.md` gains **§15**, and the phase-2 row is marked done. Pairs with [Module-Rust#2](https://gitea.whitlocktech.com/RunicGateway/Module-Rust/pulls/2) (merged) and release [v0.1.0](https://gitea.whitlocktech.com/RunicGateway/Module-Rust/releases/tag/v0.1.0). ## The criterion is met > *An operator installs the empty module from Admin → Modules and it reaches `started`.* Walked as an operator would, with the phase-1 state **torn down first** — the hand-copied `modules/rust/` directory moved aside and its `installed_modules` row deleted — so this was a first install, not an upgrade. `GET /api/v1/public/rust/servers` answered **404** before it. Paste the manifest URL → *"Installed Rust v0.1.0. Restart to load it."* → restart → `module "rust" started`. The row now carries `state = started`, the source URL and `sha256 7296c76b988c…`, where phase 1's had **nulls** in both, because a directory somebody copied has no provenance to record. Three checks that it is *serving* and not merely loaded: the public route answers **200**, the player and admin tiers answer **401** (tier gates on, not bypassed), and all five `/rust` paths appear in `/api/docs.json` — the fragment merged into core's own spec. The volume received **exactly the twenty files the include list names**. No tests, no `server/scripts/`, no `ci/`, no `client/src/`, no `node_modules`, no dotfiles. ## What the phase found **The starting position was worse than the row implied.** Phase 1 built five guards and ran every one by hand, because the repo had no `.gitea/workflows/` at all — nothing gated the branch that gets released, and there was no way to release it. Hence **D4**: the phase covers the gate as well as the release. **The frozen manifest answers a question §13 had to take on trust.** §13's own registration comment says `/rust` was "checked against core's mount tables rather than assumed" — and names the limit: core mounts several public routes at a **tier root** (`/status`, `/version`) that the loader's collision probe cannot see. The job diffs a real core's route table with and without the module. Locally and then in CI, against the same pinned ref, agreeing exactly: ``` route manifest up to date (280 routes) wrote routes.manifest.json (282 public + 4 internal) routes.manifest.json is current — 6 routes, all documented ``` **The bundle carries no `node_modules` (D5), and the emptiness is asserted rather than assumed** — the point of the decision is that the day it stops being true is a loud day. Verified by breaking the include list, which names the exact edit. **`REGISTRY_TOKEN` was already configured.** That was the one prerequisite this work could not check for itself — the bot identity can read neither repo nor org Actions secrets. The credential check exists because the answer was unknowable from here, and the first release ran clean through it. ## Two things §15 is honest about - The **Restart the server** button was *not* exercised; the restart was done from the shell. That button needs a supervisor to bring the process back, which the shipped `docker-compose.yml` provides and a bare `npm start` does not — and it is core's behaviour, not this module's. - The module's two tables were left in place when the row was deleted, so the rig's `main` server row survived the reinstall. The schema fragment replayed on boot (`statements: 2`), exactly as R12 requires of a fragment that runs every time. ## One rig finding, not a module finding Docker Desktop's Linux engine was found dead — WSL distro stopped, `uomm-db` exited, and `docker` answering every call with a bare `500 Internal Server Error` naming nothing. Recorded because it presents as the *website* being broken, and `CLAUDE.md` points every smoketest at that one container. ## Noticed, not changed `modules/rust/README.md` still describes `CARBON.md` as "**not yet proven on a live Carbon server**". §14.5 of PLAN.md disproves that — R19 was proven on Carbon 2.0.259.0. It is outside this phase's scope so I have left it; worth a one-line fix whenever someone is next in that file. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4
wtclaude added 1 commit 2026-09-16 10:43:04 +00:00
PLAN.md gains §15 and the phase-2 row is marked done.

What the phase found worth recording:

- The starting position was worse than the row implied: phase 1 built five
  guards and ran every one by hand, because the repo had no .gitea/workflows at
  all. So the org lead widened the phase to include the gate, not only the
  release (D4), and the frozen-manifest job shipped with it rather than waiting.
- That job answers a question §13 had to take on trust. Core mounts /status and
  /version at a tier root where the loader's collision probe cannot see them, so
  phase 1 could only check /rust by reading. Locally and in CI, against the same
  pinned core: 280 core routes, 6 added, all documented, none of core's moved.
- The bundle carries no node_modules (D5), and checkBundle.js asserts the
  emptiness rather than assuming it — the day a dependency appears is meant to
  be a loud day. Verified by breaking the include list.
- No Sonar for the three Rust repos until phase 19 (D6).
- The criterion is met. v0.1.0 published, downloaded, hashed independently
  (7296c76b… matches the manifest), and installed from its manifest URL through
  Admin → Modules into a core with the phase-1 directory and row torn down
  first. The volume received exactly the twenty files the include list names;
  the row reads started with a source and a sha where phase 1's had nulls; the
  public route answers 200, the player and admin tiers 401, and all five /rust
  paths merged into core's own spec.
- REGISTRY_TOKEN was already configured — the one prerequisite this work could
  not check for itself, since the bot can read no Actions secrets.
- One rig finding: Docker Desktop's Linux engine was found dead and answered
  every call with a bare 500, which presents as the website being broken.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4
whitlocktech merged commit ddf777fd8c into main 2026-09-16 10:51:03 +00:00
whitlocktech deleted branch docs/rust-phase-2 2026-09-16 10:51:04 +00:00
Sign in to join this conversation.
No description provided.