Files
docs/modules/rust/PLAN_LAST_FIXES.md
wtclaude d5de24d839 docs(rust): record the walk clean-up (PLAN_LAST_FIXES section 7)
A's two test grants deleted and revoked on both rigs. The Oxide rig loses the
walk owner, RgKitProbe and RgWalk, and gets RaidableBases' config back from
the walk's backup, followed by a restart (N2). The Steam key is left to the
org lead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-10-22 07:00:10 -05:00

20 KiB
Raw Blame History

module-rust — the last fixes before the cutover

Status: all six stages done, 2026-10-22. Every fix in §3 is built, and §8 names the PR for each. The questions in §5 were answered on 2026-10-21, and the stage 4 decisions on 2026-10-22. Stage 6 released protocol 14 and cut the Rust repositories and website over to main the same day (§8.1). §7's clean-up was done the same day; the org lead rotates the Steam key himself. Written 2026-10-21 after the end walk's in-game pass, as a plan. It continues PLAN_REDESIGNS.md §9.1, which lists W1–W20 and N1 from the passes without a player. This document adds what the in-game pass found and puts everything in one list, in the order it should be built.

After this list: the protocol 14 release, then the cutover of the four Rust repos from edge to main (PLAN.md §34). The release does not need §6's rows with a second player unless the org lead decides otherwise (Q38).


1. The in-game pass, 2026-10-21

Builds Rust 25902425, Oxide 2.0.7830, Carbon 2.0.262 (each the latest that morning)
Site website edge (MODULE_API 1.17.0, Steam sign-in) with Module-Rust edge, on the walk database, at 127.0.0.1:3270
Bridge Rust-Plugins edge on both rigs, protocol 14 sidecars
Player A, the org lead's own Steam account, linked through Steam sign-in
Phone the Android emulator on the walk machine, app from Android-app edge

The rows are in PLAYER_WALK.md, "The end walk's in-game pass".

Part Result
1, Steam sign-in on the web 1.1–1.6 pass. 1.7 needs a second player (§6)
2, in game 2.1, 2.2, 2.4–2.14 pass. 2.11 passed on Carbon. 2.3 passed for its NPC count; that PvP is off and the lock holds needs a second player (§6). 2.9 and 2.10 passed once W21 was patched on the walk site
4, the phone 4.2 and 4.3 pass. 4.1 reaches steamcommunity.com; the org lead chose not to finish a Steam sign-in on the emulator, and Part 1 covers the sign-in itself. 4.4 was not run
Carbon's share Only 2.11 was walked. The org lead dropped the rest: the bridge file is the same on both frameworks, and Carbon's halves of every integration passed without a player on 2026-10-19

2. What the in-game pass found

# Where What
W21 Module-Rust A reward's message never reaches the game. server/permSync.js pushes groups, grants, credits and retire, but not notices. The model builds the notices and the hold keeps them, so they are dropped only at the push. No kit reward, lend or give has ever told its player anything. The sidecar passes notices through, and the plugin shows them as written. The second real bug.
W22 docs Three rows of PLAYER_WALK's in-game pass expect the wrong thing. 2.8: items on the extra page go to the inventory only when the first page is full. Backpacks first moves them into free slots on the pages that are left. 2.9: a reward's message goes to chat or a popup, as the step chooses, not both. Before you start: it names neither BetterChat on both rigs nor the title rules that 2.1, 2.4, 2.12 and 2.13 read.
W23 docs rbevent setowner A reads as a purchase, not a lock. RaidableBases 3.2.2's TrySetPayLock takes paylock = !args.Contains("lockout"). The plain command raises OnRaidableBasePurchased, so the feed shows "bought". Only rbevent setowner A lockout raises OnRaidableBaseLocked. PROTOCOL.md §20.12, PLAN_REDESIGNS §11.4 and PLAYER_WALK 2.2 say the plain command locks.
N2 docs Reloading RaidableBases while it runs breaks it. After oxide.reload RaidableBases (three tries, two of them with bases up), its list of live raids held a null. Every hook that walks the list then threw: damage, SAM sites, player commands and /buyraid's cooldown check, so a purchase did nothing and charged nothing. A full server restart cleared it. Operators should change RaidableBases' config with a restart, never a reload. A third-party bug, but worth a line in OPERATING.md.

What the pass proved for the first time: the D333 messages on Oxide and Carbon, online and on waking, in chat and as popups (once W21 was patched); a payment made while the player was offline and told on waking; a command reward with the player's real id and name; a two-page backpack in the staff view, on the account page and in the app, with another player's backpack refused; the extra page's items going to the inventory and then to the ground; the four titles in chat; and on Carbon, a give, a lend and a bigger backpack reaching a real player who had joined it. (W17 is still true for players who have never joined.)


3. The whole list

From PLAN_REDESIGNS §9.1 (W1–W20, N1) and §2 above. Bold rows are real bugs, and everything else is wording, lag or docs. "Proposed" is a suggestion for the org lead, not a decision.

3.1 Module-Rust

# Proposed fix
W21 Send notices: held.payload.notices with the push, plus a test that a sync with an untold notice carries it. Already patched in the walk site's copy of the module for the walk.
W4 Stamp the helicopter and Bradley credit rule onto each feed row at ingest, and read the stamp when the line is drawn. Rows from before the fix keep today's reading.
W3 Calling the Travelling Vendor while one is out says so ("one is already out") instead of "called 1".
W6 "A locked crate dropped by a Chinook is being hacked."
W7, W11 Before an "is it loaded" refusal, ask the sidecar live rather than reading the 30-second status poll.
W8 A RaidableBases profile write's audit row names RaidableBases, not "@data".
W10 The backpack sizes picker lists each size once, naming every server that offers it.
W13 A profile name on both servers shows each server's difficulty when they differ.
W14 Capital letter after the full stop.
W15 Both of Economics' refusals of a staff deposit answer 409.
W16 failedNote names only what happened (at-limit alone reads "at the balance limit").
W17 When the sync report's notLanded names a lent or given permission, the run log and the server's sync state say so ("lent to 2; 1 lands when they first join Carbon") instead of "in sync". It does land once they join, because every sync pushes the whole set.
W18 Read the event's own time limit from the server for the placement note, or drop the number.

3.2 The bridge (Rust-Plugins)

# Proposed fix
W9 A rolled-back RaidableBases profile write reports RaidableBases' own error, not the tail of the server log.
W12 raid.ended carries the base's id, and its run and key when a run made it, as PROTOCOL says.

3.3 Core (website)

# Proposed fix
W1 On a reconnect, check expiry before marking a resource orphaned, so the log shows only resource.expired.
W2 A phase waiting to advance with its steps done reads "Phase p1: steps done, waiting to advance".
W5 A dry run that passed on a draft counts for the version published from that draft when the spec is unchanged.
W19 Module-uo and Module-Rust cannot share a site. A design change, so it needs Q37 first.

3.4 Plan against core

# Proposed fix
W20 §14.3.4's "manual retry" cannot be done, because core retries only a failed step. Q39 decides whether to change the plan or core.

3.5 Docs

# Proposed fix
N1 OPERATING.md: installing RaidableBases' free edition over a paid pack rewrites the pack's profiles and drops their bases.
N2 OPERATING.md: change RaidableBases' config with a server restart, never a reload.
W22 Correct PLAYER_WALK 2.8, 2.9 and "Before you start" as §2 says, and trim "Carbon's share" to 2.11, as walked.
W23 Correct PROTOCOL.md §20.12, PLAN_REDESIGNS §11.4 and PLAYER_WALK 2.2: rbevent setowner A lockout locks, and the plain form reads as a purchase.

4. Order of building

One PR per repo per stage, each announced, with a pause for the org lead before the next stage.

  1. The two bugs, W21 and W4 (Module-Rust), each with its test, then a walk-site check: one lend with a message (W21), and a past helicopter line read under a changed credit rule (W4).
  2. Module-Rust's small fixes: W3, W6, W7/W11, W8, W10, W13–W18.
  3. The bridge: W9, W12. A protocol change only if W12 adds fields PROTOCOL already lists, so no version bump.
  4. Core: W1, W2, W5, and W19 once Q37 is answered. W19 may need a MODULE_API minor bump and a new core pin in Module-Rust and the Integration Kit.
  5. Docs: N1, N2, W20 (per Q39), W22, W23, and this document's status.
  6. The release and the cutover, on the org lead's go.

5. Questions for the org lead

Q37 — W19, two game modules on one site. Today admin.users.detail takes one provider, so a site with Module-uo and Module-Rust starts without the second. For example, an admin opens a user who plays both games:

  • (a) Tabs: the user page shows a UO tab and a Rust tab, one per module that fills the slot. The slot takes several providers.
  • (b) Stacked: each module's panel appears one under the other on the same page.
  • (c) Leave it: one game module per site, and core refuses the second with a clear message at boot.

Q38 — the release and the second player. Part 3 (hand revive, healing, a PvP kill, the map walk, events step 7), 1.7 and 2.3's PvP/lock check need a second player. Do the release and cutover wait for them, or go ahead and walk them when a second player is free?

Q39 — W20, the manual retry. With Dangerous Treasures' fifteen-minute warm-up, core's automatic retry already succeeds on its third try. Either (a) PLAN_REDESIGNS §14.3.4 drops "the manual retry", or (b) core lets staff retry a step that is still pending.

Q40 — what the walk leaves on the rigs. BetterChat was added to the Oxide rig for the titles, and the walk site now has title rules for the richest, raids, treasures and guarded crates. Keep both, or remove them with the rest of §7?

Answered 2026-10-21, each with the recommended option:

  • Q37: (c), and stricter at boot (2026-10-22). One game module per site. The proposal was a clear message when the second module's slot collides. The org lead chose a full stop instead: the first module directory by name loads, and every other is refused before its code is required, as the installer already refuses one. No MODULE_API change (MODULE_SYSTEM.md §2.5, MODULE_API.md §4.2).
  • Q38: the release and the cutover do not wait for §6's second-player rows. They are walked when a second player is free.
  • Q39: (a). PLAN_REDESIGNS §14.3.4 drops "the manual retry". Docs only.
  • Q40: keep both. BetterChat stays on the Oxide rig, and the four title rules stay on the walk site.

6. Still owed, with a second player

1.7 (someone else's Steam account refused), 2.3's no-PvP-damage and lock-holds, all of Part 3, and the second-player rows of 4.4. They are written in PLAYER_WALK and need no change.


7. Cleaning up after the walk

Done on the org lead's go, after stage 6. Q40 keeps BetterChat on the Oxide rig and the title rules on the walk site, so neither is in this list:

  • Oxide rig: remove A from the owners (removeowner, then server.writecfg). Remove the walk-only RgKitProbe plugin, which holds god mode and a teleport command, and the RgWalk stand-in plugin. Restore RaidableBases' config from the walk's backup, which takes away the 100-coin Easy and Medium buy costs, and restart the server rather than reloading (N2).
  • Walk site: remove A's test grants (backpacks.use on Oxide; the backpacks.use given on Carbon).
  • Steam: rotate the Steam Web API key, which was pasted into the chat that ran the walk, and put the new one in Admin → Auth → Steam.
  • The rigs' bridge: done in stage 6 (§8.1). Both rigs run the released files of bundle 2026.10.22.
  • W21 landed in stage 1 (Module-Rust#54), so the walk site's hand patch is no longer needed.

Done 2026-10-22, except the Steam key, which the org lead rotates himself.

  • Walk site: A's two grants were deleted (#5 backpacks.use on rust-oxide, from staff; #7 backpacks.use on rust-carbon, an event give). A sync then applied one revoke on each rig, and both read in sync. The walk site runs Module-Rust v0.5.0 byte for byte as released, so the W21 hand patch is gone with it.
  • Oxide rig: removeowner and server.writecfg left users.cfg empty. RgKitProbe and RgWalk were deleted, and Oxide unloaded both. RaidableBases' config was restored from the walk's backup, so its only difference was that Easy and Medium went back to 0. The server was then saved and restarted. RaidableBases 3.2.2 loaded with no errors, the config was still at 0 after the boot, and neither walk plugin came back.

8. What was built

One PR per repo per stage, each merged into edge (the Rust repos and website) or main (docs) by the org lead.

Stage PR Fixes
1, the two bugs (2026-10-21) Module-Rust#54 W21: the push sends notices. W4: the credit rule is stamped on each helicopter and Bradley row at ingest and read from the stamp; a row from before the fix is read by the current rule
2, Module-Rust's small fixes (2026-10-21) Module-Rust#55 W3 (reads the bridge's already-out as a success that called 0), W6, W7 and W11 (a "not loaded" refusal is confirmed against the sidecar, at most every 5 s and within 3 s), W8, W10, W13–W16. W17: the sync state only, "in sync · N wait for their player to join"; the run log is unchanged, because core has no way for a module to add a line to it. W18: the number is dropped from the note
3, the bridge (2026-10-21) Rust-Plugins#43 W3 (world.error already-out), W9 (RaidableBases' own log lines since the write), W12 (raid.ended carries id, and runId and key for a run's base). No protocol bump, because PROTOCOL already listed W12's fields. Walked on both rigs
4, core (2026-10-22) website#219, Module-Rust#56 W19: one module per site at boot (Q37). W1: a zone reports until, and a reconcile files a resource gone past it as expired. W5: a draft's passing dry run carries over by spec fingerprint. W2: "Phase p1: steps done, waiting to advance". No MODULE_API bump. Walked on the walk site
5, docs (2026-10-22) docs#367 N1 and N2 in OPERATING.md. W20 in PLAN_REDESIGNS §14.3.4 (Q39). W22 and W23 in PLAYER_WALK, PROTOCOL §20.12 and PLAN_REDESIGNS §11.4. The wire changes stages 2–3 made without a doc edit (PROTOCOL §20.5's already-out, §20.12's rollback log). Stage 4's core docs: MODULE_SYSTEM §2.5, MODULE_API §4.2 and the resource until, EVENTS §D, §I, §K and §L, and BACKEND_DESIGN's three new columns
6, the release and the cutover (2026-10-22) website#220, Rust-Plugins#44, Rust-Link#32, installer#42, Module-Rust#57, Module-Rust#58, this document's PR edge → main in five repositories, and core re-pinned to main in Module-Rust. Protocol 14 released: bundle 2026.10.22, Module-Rust v0.5.0 (§8.1)

8.1 Stage 6, as built (2026-10-22)

Before anything merged, the org lead answered two questions. The Integration Kit's re-pin to core 1.17.0 is a separate PR after this stage. The rigs move to the released bridge in this stage. The installer cannot run inside a Pterodactyl server, because the panel offers no shell. So the org lead chose to upload the bundle's exact files and restart, and to prove the installer itself over scratch roots.

  • The order: website first, because Module-Rust's coreApi is ^1.17.0 and 1.17.0 was only on website's edge. Next came Module-Rust's re-pin, then the three bridge-side repositories together, then the bundle. Module-Rust went last, after the bundle had composed. On 2026-10-09 the module was out eleven minutes before its bundle; this time the order held.

  • The PRs: website#220, Rust-Plugins#44, Rust-Link#32 and installer#42 (edge → main). Module-Rust#57 moved ci/core-ref.json from website's edge sha 9a1654f to the main sha 6890a74. Module-Rust#58 (edge → main). RunicNPC had nothing new and stays at v1.0.0. No merge deleted edge this time.

  • The releases, each checked against its own SHA256SUMS:

    Repository Release What was checked beyond the checksums
    website main at 6890a74 MODULE_API 1.17.0. The image build and deploy passed.
    Rust-Plugins v0.3.0 Manifest: protocol 14, runicnpc_api 6, Oxide 2.0.7585, Carbon 2.0.259. Each of its four files matches its manifest hash, the new RunicGatewayRaids.cs among them.
    Rust-Link v0.3.0 Both sidecar binaries, the launcher and the egg JSON. The Linux binary answers 0.3.0 (protocol 14).
    installer v0.8.0 --version answers 0.8.0.
    Module-Rust v0.5.0 Manifest rust 0.5.0, coreApi ^1.17.0, the client chunk built in. The release JSON's sha256 is the tarball's.
  • The bundle: v2/rust/current.json moved from 2026.10.09 (protocol 13) to 2026.10.22: protocol 14, Rust-Link v0.3.0, Rust-Plugins v0.3.0 and RunicNPC v1.0.0. Each hash in it equals the one in its release's SHA256SUMS, RunicNPC's included. It composed in run 201. Run 200 came between the plugin's release and the sidecar's, and Gate 1 refused the pair, as it did on 2026-10-09.

  • One red run, harmless: Rust-Link's push-triggered release (run 39) waited for a runner. Meanwhile compose run 200 dispatched the same workflow (run 40), which released v0.3.0 first. Run 39 had computed v0.3.0 as well. It pushed the same tag as a no-op and got 409 from POST /releases. The step stops on any 4xx before uploading, so v0.3.0's assets and SHA256SUMS were unchanged afterwards. The release engine works as designed. Only the red mark remains.

  • The installer and the egg from the real bundle, in the egg's own installer image (ghcr.io/ptero-eggs/installers:debian), over a scratch Oxide root and a scratch Carbon root, with nothing bypassed:

    • Installer v0.8.0 install --game rust resolved 2026.10.22. It placed the bridge, the three helpers and RunicNPC v1.0.0, each identical to its release, and a sidecar at the bundle's hash that answers 0.3.0 (protocol 14). doctor passed the record, the plugin, the helpers, RunicNPC, the plugin config and "2026.10.22 is current". It failed the service and the sidecar, as a relocated state directory always does. It warned that Kits and ZoneManager are missing, which a scratch root lacks.
    • The bridge section of Rust-Link v0.3.0's egg placed the same files, the sidecar and launcher at mode 755 with the bundle's hashes, and the banner. It wrote rust-link/bundle.json as 2026.10.22, protocol 14, RunicNPC v1.0.0 (api 6).
  • The rigs, on Rust 25902425, Oxide 2.0.7830 and Carbon 2.0.262 (each the latest that day). Each world was saved and the server stopped. The bundle's exact files went up through the panel's file API: the four plugin files from the v0.3.0 tarball, RunicNPC.cs from v1.0.0, the v0.3.0 sidecar and the launcher. Their sizes were checked against the release, and then each server was started. Both load Runic Gateway v0.3.0 at protocol 14, the three helpers and RunicNPC v1.0.0 with no compile errors, and both sidecars answer /health at protocol 14 with the plugin connected. Before this, the rigs ran stage 3's hand copy. It was the same code but for the version stamps and CRLF line endings. rust-link/bundle.json on the rigs still says 2026.09.26.5: only the egg's install writes it, and the rigs were not reinstalled.

  • The walk site: core on website main (6890a74). Module-Rust v0.5.0 was installed through Admin → Modules from its release URL (module-rust-0.5.0.json, sha256 checked, replaced), then restarted through the same screen's restart route. It came back started at 0.5.0, and both rigs read online at protocol 14 on Admin → Rust → Servers.

  • Not done: a panel reinstall from the released egg. The panel's egg 25 is from 2026-09-26, and the panel has no API for writing an egg, so testing the released egg by reinstall still needs someone to import egg-rust-runicgateway.json by hand (as on 2026-10-09).