docs(modules): module-rust phase 0 as built — the rig is current, and four plan claims were wrong #251
Reference in New Issue
Block a user
No description provided.
Delete Branch "docs/rust-phase-0"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What & why
Phase 0 of
docs/modules/rust/PLAN.md§5 — the rig. Follow-up to #249 and #250.D:\rustis now on build 25230300 with Oxide 2.0.7716 and all four base plugins loaded at exactly the versions R6/R17 name (Kits 4.4.9, Clans 0.2.10, Popup Notifications 0.2.1, Zone Manager 3.1.14). They compiled first time on the new build.The interesting half is that the rig disproved four things the plan asserted. Adds §12 and wires the corrections into §4, R2, R5 and R17.
1. The rig's own script never updated anything (§4)
The plan recorded
start.batas "updatesC:\rustserver, runsD:\rust" and "fixed" it by changing the path. The path was never the problem. steamcmd requires+force_install_dirbefore+login, and the script had it after:So the flag was discarded and every update run in the rig's history errored out without updating any directory. That — not a misdirected install — is why
D:\rustfell a wipe behind, and it is corroborated byC:\rustserversitting at the same stale buildid rather than a newer one.The Oxide re-install is routine and is recorded as such. One narrow consequence still belongs to phase 18: because
app_updateleavesOxide.Core.dlland the rest in place, adoctorcheck written the obvious way — "doesoxide/exist", "are Oxide's assemblies present" — passes on a server that is mid-routine. CompareAssembly-CSharp.dllagainst the Oxide build sodoctorreports the real state rather than a directory listing.2. Four rules the R2 permission push must obey (§12.2)
Verified live, granting and revoking through both the console command and the API. The one with teeth:
permission.GrantUserPermissionsilently no-ops when the permission is not registered.void, no throw, no log — the consoleoxide.grantat least answersPermission 'x' doesn't exist, but the API path R2 actually uses says nothing. Since R2's recovery story is "the site re-pushes the whole set on connect", a re-push into a server missing one plugin is a silent partial, and the site believes it pushed privilege the game never received.Also:
RegisterPermissionwarns about a foreign prefix but registers anyway (so the site can make a grant stick for an absent plugin, at the cost of a warning); and a player who has never connected is in no group yet can hold direct grants — so grants and groups have different reach for offline players, which phase 7 currently treats as two spellings of the same thing. R16's offline entitlement is safe; a group-shaped one would not be.3. R5's claim about the Clans plugin was a grep artefact (§12.3)
The plan says the plugin raises "exactly three hooks —
OnClanCreate,OnClanChat,OnAllianceChat— none of which is a membership transition" and concludes it cannot answer core's provider questions at all.It raises nine. The six that were missed are invisible to a search for
CallHook("OnClan…because the name is aconstat the call site:OnClanMemberJoined,OnClanMemberGoneandOnClanDisbandedcarry the full member list, andOnClanUpdate(tag)fires on promote and demote — the exact transitions first-party lacks and that R5 calls "the one gap to design around".The decision does not change, but its stated reason had to. First-party stays the provider source because every server has it and the plugin is an optional install; feeding a provider from something optional makes Teams conditional on a mod. Phase 17 now gains event-driven leadership as a sharpening of phase 9's snapshot rather than a replacement.
Two smaller things from the same read:
Clansraises each hook name twice per transition (Rust-typed and Universal-typed, both arity 3 — a loosely typed subscriber double-counts every join), and it callsAPI_RegisterThirdPartyTitleitself, so R15's BetterChat work will be the second title provider on any server running both.4. ZoneManager's owner scoping is narrower than R17 assumed — a safety correction (§12.4)
R17 leans on
EraseTemporaryZone(owner, zoneId)being "scoped to the owner" as "most of ch. 4's persisted ownership registry". The scoping is one-directional:zoneOwneris null for every permanent zone, i.e. every zone an operator made by hand — soEraseTemporaryZone(us, "<operator's zone>")deletes it and returnstrue, indistinguishable from erasing our own. Observed live. Phase 12's own id map is therefore load-bearing, not convenient: it must refuse to erase any id it did not record creating, because ZoneManager will not refuse on our behalf.Also recorded there:
GetPlayersInZonereturns an empty list for an unknown zone as well as an empty one (the absence-of-an-answer trap again), and NPCs never enter a zone's player list.5. One acceptance criterion stays open, and not by choice of method (§12.5)
The grant half is done — proven in both directions for an online-known and a never-seen player, through the same
UserHasPermissioncall every third-party plugin makes.The occupancy half cannot be closed headlessly. A plugin's permission check reads
return !player || permission.UserHasPermission(...), and a command from RCON has noBasePlayer— so the server console is unconditionally allowed and no console session can ever observe a gate closing. Zone occupancy has the same shape from the other end:baseEntity is BasePlayer { IsNpc: false }excludes NPCs by construction, so only a real connected player puts a name in that list.Everything up to the body was proven: a zone created through the API, listed by both the probe and ZoneManager's own
zone_list, read for occupancy (a real empty list, so the call resolved), and erased. What remains is one person, connected, standing inside it.This is flagged as a standing property of the rig, not a phase-0 leftover — phases 7 and 12 have acceptance criteria of the same shape.
How it was tested
Everything in §12 was observed on the live rig, not read off a source:
D:\rust; all four plugins compiled and loaded (oxide.plugins,oxide.version).RGProbe.cs, a throwaway Oxide plugin exposing Oxide's permission API and ZoneManager's by-name API as console commands. Both kept in the phase-0 scratchpad rather than committed; the probe is a reasonable starting point for phase 1's skeleton.Call()on the live server, including the unowned-zone erase.agent/hooks.tsv.oxide.show userconfirms both ids clean.One thing worth repeating from §12.0: Oxide tags its own
Puts()output with the identifier of the command being run, so a first-match-wins RCON client reads a plugin's log line as the reply and discards the real one. It produced two wrong readings before it was spotted.Checklist
AI-assisted contributions (required)
Claude Code (Opus 5). I have reviewed and understandevery change, and take responsibility for it. AI-authored commits are
marked with a
Co-Authored-By/Assisted-Bytrailer.License
(GNU GPL v3.0 or later), and I have the right to contribute it.
🤖 Generated with Claude Code
https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4