docs(rust): plan fixes — the first player walk's findings, gating the cutover
PLAN_FIXES.md plans what the Oxide pass of PLAYER_WALK.md found on 2026-09-26: fifteen fixes (F1-F15, F15 corrupts every non-ASCII site-to-game string including config saves; F9 rolls back valid config edits on a cold compile), the interface and walk-doc corrections, and the org lead's decisions D159-D168 (D160 reverses D31: the site owns every permission and group). Recommends the fixes land before Module-Rust's cutover (phase 19) and the redesigns follow it. PLAN.md gains a pointer in its status line and §35; the rust README lists the new file. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
This commit is contained in:
338
modules/rust/PLAN_FIXES.md
Normal file
338
modules/rust/PLAN_FIXES.md
Normal file
@@ -0,0 +1,338 @@
|
||||
# `module-rust` — plan fixes
|
||||
|
||||
**Status:** plan, awaiting the org lead's approval, 2026-09-26. **The gate before Module-Rust's cutover
|
||||
(phase 19, [`PLAN.md`](PLAN.md) §34, D145).** Everything here comes from the first walk of
|
||||
[`PLAYER_WALK.md`](../../rust-link/PLAYER_WALK.md) with a real player in the game — the Oxide pass, walked by
|
||||
the org lead on the `rust-oxide` rig with every frame checked on the console, the sidecar and the site's
|
||||
database. The Carbon pass has not been walked yet and may add to this document.
|
||||
|
||||
This is a companion to [`PLAN.md`](PLAN.md), not a replacement: its decisions continue PLAN.md's numbering
|
||||
(D159 onward), and where the two disagree this one is later and wins. It has three kinds of content, and
|
||||
they gate the cutover differently (§6):
|
||||
|
||||
- **Fixes** (§2) — the plugin, the sidecar or the site does something other than what the plan and the
|
||||
protocol say. Fifteen, F1–F15.
|
||||
- **Interface and walk-doc corrections** (§3) — what works but misleads, and where the walk doc itself is wrong.
|
||||
- **Changes the org lead decided during the walk** (§4) — new behaviour, each with its decision of record.
|
||||
|
||||
---
|
||||
|
||||
## 0. What the walk was
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Date | 2026-09-26, 16:40–21:05 UTC |
|
||||
| Rig | Pterodactyl server 17 `rust-oxide`, Oxide, world 3000 / seed 1234 |
|
||||
| Plugin | Rust-Plugins **v0.1.1**, the released file, byte-identical |
|
||||
| Sidecar | the phase-17 build, protocol 12 (pre-D155) |
|
||||
| Site | the phase-18 walk core on :3270, Module-Rust at phase 17 |
|
||||
| Extra plugins | Kits 4.4.9, ZoneManager 3.1.14, BetterChat 5.2.15, PopupNotifications 0.2.1, and — added during the walk — PermissionsManager 2.1.2 and ZoneDomes 2.0.2 |
|
||||
|
||||
**Scorecard.** Player walk: 1–7, 9, 10 pass (4 and 9 with findings), 8 needs a second player. Identity:
|
||||
1–5 pass, 6 behaves as written but that behaviour is F5. Permissions: all seven pass, three with findings.
|
||||
Configuration: 1, 3, 4, 6, 7 pass; 2 failed as written (F9) and passed on a retry; 5 not applicable; 8 proven
|
||||
at the site's guard only. Events: 1–6 pass in the game, 6's frame is F13; 7 needs several players. Rewards:
|
||||
1, 3, 4, 6 pass (6's text is F15); 2 is covered by 3; 5 deferred. Chat titles: 1 authored, not earned; 2–5
|
||||
not walked. Map and phone walks: not walked (two accounts, the app).
|
||||
|
||||
## 1. Decisions of record
|
||||
|
||||
Taken by the org lead during and straight after the walk.
|
||||
|
||||
| # | Decision |
|
||||
|---|---|
|
||||
| **D159** | **"Gathered" is everything a player harvests** — swings, the bonus on the final hit, and what is picked up off the ground. Rejected: swings only (the leaderboard would disagree with the inventory). F1. |
|
||||
| **D160** | **The site is the source of truth for all permissions and groups** — those that were on the server before the site, those added in the game, and those added on the site. Everything flows back to the site. **This reverses D31**, under which a permission the site had not authored was "somebody else's business" and never enumerated. |
|
||||
| **D161** | **Each server has a policy for a change made in the game: revoke, adopt, or auto-adopt. The default is auto-adopt.** |
|
||||
| **D162** | **The permission screen follows uMod PermissionsManager's flow** (the reference is PermissionsManager 2.1.2 on the rig, screenshots in the workspace's `perms-screenshots/`): all players ⇄ all groups → a player or group → its plugins → that plugin's permissions with Granted / Revoked, Grant all / Revoke all → a player's groups, a group's players, Remove all. |
|
||||
| **D163** | **Every subject on that screen shows the linked website account, if any, and the in-game name — or the Steam id when the server has no cached name.** |
|
||||
| **D164** | **A "kit open for everyone" event is a lease paired with a use credit.** `core.lease` on the kit's permission plus `rust.kit.entitle` (one use per recipient, D103, withdrawn on revert), offered as a template — and the lease form warns when the kit's own limits mean players have already used it up. Rejected: a new lease that rewrites Kits' usage data, which D103 deliberately avoided. |
|
||||
| **D165** | **The live map's monument markers get a per-type toggle, and the default shows the major monuments only.** Substations (18 on the rig's map), caves and similar small places are off unless staff turn them on. |
|
||||
| **D166** | **The zone step offers ZoneManager's own flags and settings**, read from the installed ZoneManager, not a hard-coded list. |
|
||||
| **D167** | **ZoneDomes is an optional dependency.** The zone step gains a "show a dome" option; the bridge adds the dome and removes it with the zone. |
|
||||
| **D168** | **When a plugin we depend on does not expose what we need, we may write a small helper plugin for it.** It ships from Rust-Plugins beside the bridge, is optional, and is detected at hello like the other integrations. The bridge keeps calling only public APIs (R2); the helper is where a gap in someone else's plugin gets bridged. |
|
||||
|
||||
**One more, leaning but not yet decided:** Steam as a first-class sign-in provider on the website (§4.8).
|
||||
|
||||
## 2. Fixes
|
||||
|
||||
Grouped by severity. Each says what the walk saw, why, and the fix. Line numbers are against
|
||||
Rust-Plugins v0.1.1 and Module-Rust at phase 17.
|
||||
|
||||
### 2.1 High
|
||||
|
||||
**F15 — every non-ASCII character the site sends to the game is corrupted.** *(Rust-Plugins)*
|
||||
An event announcement's em dash arrived as `â` in chat and in the console. `RunicGateway.cs:787` reads the
|
||||
socket byte by byte and appends `(char)buffer[i]` — UTF-8 decoded as Latin-1. The write side (line 756) is
|
||||
correct, so only site→game text breaks: announcements, news in chat and popups, chat titles and styles,
|
||||
kit and zone names — **and configuration saves**: a file saved from the website that holds any accented
|
||||
letter, dash or emoji is written back to disk mangled. Configuration step 3 passed only because the file
|
||||
was ASCII.
|
||||
*Fix:* collect bytes per line and decode the finished line with `Encoding.UTF8`; a multi-byte sequence split
|
||||
across two reads must survive. *Test:* é, — and an emoji through an announcement and a config save, on both
|
||||
frameworks. Add the same line to the walk.
|
||||
|
||||
**F9 — a valid configuration edit is rolled back because the reload window is shorter than a cold compile.**
|
||||
*(Rust-Plugins, Module-Rust)*
|
||||
Kits' chat command changed from the site → "The plugin did not come back, so the old file was put back
|
||||
automatically". Oxide's log: the compiler had idled out (it stops after 60 s, `oxide.config.json`), restarted,
|
||||
compiled Kits in 2.85 s, and loaded it — just after `ConfigReloadWindowSeconds = 4f` (line 4087). The retry,
|
||||
needing no compile, passed. The window races work whose length the plugin does not control: host speed,
|
||||
plugin size, Carbon's own compiler. Operators must not have to tune Oxide to make the site work.
|
||||
*Fix:* answer the save at once ("saved, reloading…") and deliver the outcome as a frame when it arrives, under a
|
||||
long ceiling (30 s or more). Roll back on a real failure — Oxide logs "Failed to initialize plugin" the moment
|
||||
it happens (configuration step 4 showed it) — not on a clock. Protocol-visible (§5).
|
||||
|
||||
**F10 — the rollback can say "did not come back" about a plugin that did, and can race it.** *(Rust-Plugins)*
|
||||
After F9's timeout the plugin restored the file and fired a second reload, but the log shows one compile, so
|
||||
which file the running plugin read depends on timing. *Fix:* never restore while a compile of that plugin is
|
||||
in flight, and report what actually loaded. F9's fix removes the cause.
|
||||
|
||||
**F12 — a player already inside a zone when it is created or restored is not "in" it.** *(Rust-Plugins)*
|
||||
After a restart the bridge re-created the event zone correctly (same id, same place, row still `confirmed`);
|
||||
the org lead woke up 18 m inside it and ZoneManager's `IsPlayerInZone` said nobody. The same happened when a
|
||||
zone opened around a player. ZoneManager counts a player only on trigger *enter*, and the participation tally
|
||||
asks it every five seconds (§29.7) — **so after any restart mid-event, everybody already in the arena scores
|
||||
nothing until they walk out and back in.**
|
||||
*Fix:* after creating or re-creating a zone, have ZoneManager re-evaluate who is inside; if its API has no way
|
||||
to, that is D168's case (a helper), or the tally measures distance itself for zones the bridge made. Walk it on
|
||||
Carbon too.
|
||||
|
||||
**F13 — the `world.expired` frame leaves with its kind overwritten.** *(Rust-Plugins, protocol)*
|
||||
Three zones expired in the game exactly on time; all three frames were filed as `kind: "zone"`. Line ~7310
|
||||
builds `Frame("world.expired", "event")` and then sets `frame["kind"] = e.Kind`. [`PROTOCOL.md`](../../rust-link/PROTOCOL.md)
|
||||
§15's example has no field for the entity's kind, so the collision never showed in the spec. The walk's own
|
||||
check (`/events?kind=world.expired`) cannot pass. Present since protocol 9.
|
||||
*Fix:* send the entity kind as `what`, the name the site's resource rows already use; amend §15. Protocol bump.
|
||||
|
||||
### 2.2 Medium
|
||||
|
||||
**F1 — `gathered` counts swings only.** *(Rust-Plugins)* 825 wood in the inventory, 587 tallied; 20 cloth from
|
||||
hemp, none. The tally's shape was right (60-second deltas that sum). *Fix (D159):* also count
|
||||
`OnDispenserBonus` and `OnCollectiblePickup`, and `OnGrowableGathered` for farmed plants; add all three to
|
||||
`ExpectedHooks` so `rg.hooks` shows them. PROTOCOL.md §8.6 names the hooks that feed the counter.
|
||||
|
||||
**F3 — destroying your own building counts toward the raid stat.** *(Rust-Plugins)* The org lead broke their own
|
||||
wall and the next tally carried `structures: 1`. The `entity.destroyed` frame is right, and the site already
|
||||
skips the raid alert for an attacker authorised on the cupboard (D59) — only the counter is wrong.
|
||||
*Fix:* skip `Structures++` (~line 1700) when the attacker owns the piece or is authorised on its cupboard;
|
||||
still emit the frame.
|
||||
|
||||
**F5 — one dead server makes every wrong link code say "your code is still good".** *(Module-Rust)* With five of
|
||||
seven enabled servers offline, a spent code and a made-up `ZZZZZZ` both answered "One of the servers could not
|
||||
be reached… Your code is still good", and will until an admin disables the dead server.
|
||||
*Fix:* ingest already sees every `account.link.requested` with its server and TTL. Ask only the servers that
|
||||
issued a code in the last five minutes, and answer "unsure" only when one of *them* is unreachable
|
||||
(`links.model.js:181`).
|
||||
|
||||
**F6 — redeeming a code waits on every dead server in turn.** *(Module-Rust)* About 21 seconds, four per dead
|
||||
server; the rig sorts last, so a successful link waited too. F5's fix usually leaves one server to ask; failing
|
||||
that, ask in parallel with a short timeout.
|
||||
|
||||
**F8 — loading a missing plugin does not re-sync permissions.** *(Rust-Plugins, Module-Rust)* PopupNotifications
|
||||
came back at about 18:44; the grant that had been unresolved landed at 18:57, on the fifteen-minute audit. The
|
||||
page promises "It will land by itself when the plugin is back" — true, thirteen minutes late.
|
||||
*Fix:* emit a frame from `OnPluginLoaded` / `OnPluginUnloaded` when that plugin registers permissions; ingest
|
||||
marks the server dirty the way `perm.drift` does. §4.1 needs the same signal.
|
||||
|
||||
**F11 — the lease target picker was designed and never built.** *(website)* `core.lease`'s own comments say the
|
||||
authoring form reads the chosen lease's target source; `EventEditor.jsx` only ever renders `param.source`
|
||||
(line 299), so Module-Rust's `rust.options.grouppermissions` is never offered and the target is typed by hand.
|
||||
The walk's first attempt put it in the wrong field. Built as part of §4.3.
|
||||
|
||||
### 2.3 Low
|
||||
|
||||
**F7 — the restart re-sync fires before the game has loaded.** *(Module-Rust)* With Oxide's permission files
|
||||
deliberately wiped, the site restored its group, membership and grant — R2's central promise, proven. But its
|
||||
restart sync ran 35 s before "Server startup complete", timed out with no warning in the log (the titles push
|
||||
at the same moment did log one), and the retry 2.5 minutes later recorded "0 applied", so nothing says what the
|
||||
restart restored. *Fix:* hold the restart sync until the hello says `worldReady: true`; log a failed sync.
|
||||
|
||||
**F2 — NPC killers are named by prefab.** *(Rust-Plugins or Module-Rust)* "killed by `wolf2`". Send a display name,
|
||||
or map prefab to label on the site — whichever the killfeed page already expects.
|
||||
|
||||
**F4 — a death of a player made by another plugin carries `steamId: null`.** *(Rust-Plugins)* `UserIDString` is
|
||||
empty for players other plugins spawn; the plugin already avoids it for `entity.destroyed`. Use
|
||||
`((ulong)player.userID).ToString()` at all 13 sites. Real connected players are unaffected.
|
||||
|
||||
### 2.4 By design — a question, not a fix
|
||||
|
||||
**F14 — the site never learns that a zone expired.** Expired zones stayed `confirmed` on the run console until
|
||||
the runs were cancelled, when teardown found them "already gone" and counted that a success. PROTOCOL.md §15
|
||||
says this is intended: "The website maps it to nothing. Core learns about it through `reconcile` and `revert`"
|
||||
(D96). **The question:** should ingest mark the row `expired` once F13 makes the frame recognisable, so the
|
||||
console stops showing a live zone that is gone? Recommended: yes.
|
||||
|
||||
## 3. Interface and walk-doc corrections
|
||||
|
||||
**U-1 — "unresolved" is a sentence in the server block, not on the grant.** The org lead granted a permission for
|
||||
an unloaded plugin, looked, and saw nothing; the warning sits under the server's row next to "in sync". State
|
||||
belongs on each toggle (§4.1).
|
||||
|
||||
**U-2 — a configuration conflict offers nothing.** "That file changed on the server since you opened it", with no
|
||||
way to load the server's version or compare. Offer the server's version beside the operator's edit.
|
||||
|
||||
**U-3, U-4 — the event step editor is shaped for developers.** Type tags on every field (`LEASE * · STRING`), the
|
||||
lease is a text box with a separate "Pick from…" menu, the examples are Ultima Online values shown to a Rust
|
||||
admin, and a yes/no value is typed. The org lead: "it should be a dropdown of possible values created
|
||||
dynamically". §4.3.
|
||||
|
||||
**U-5 — Start runs the published version and says nothing about an unpublished edit.** The org lead fixed a step,
|
||||
saved, pressed Start, and ran the broken version 1. Ask "Publish and start, or start version 1?".
|
||||
|
||||
**U-6 — a lease's "10 minutes" lasted one second.** A phase with no advance rule ends as soon as its steps finish,
|
||||
and teardown takes the lease back. Nothing in the editor says so. §4.3.
|
||||
|
||||
**Walk-doc corrections** ([`PLAYER_WALK.md`](../../rust-link/PLAYER_WALK.md)):
|
||||
|
||||
- **D-1** — permission step 4 names `zonemanager.admin`, which ZoneManager does not register, and never says the
|
||||
permission must already be granted on the site to someone (true today; D160 retires the condition).
|
||||
- **D-2** — configuration step 2 names a ZoneManager setting ("Auto Show Zones") that 3.1.14 does not have. Use
|
||||
Kits' chat command, which changes something every player can see.
|
||||
- Events step 6's check (`kind=world.expired`) cannot pass until F13.
|
||||
- Configuration step 8 through the site is refused by the site first; the plugin's own guard needs a direct
|
||||
sidecar request with the rig's token.
|
||||
- Record that Kits hides a kit the player lacks permission for (`Show kits … without the permission: false`),
|
||||
so "locked" in the events and rewards walks means "not listed".
|
||||
|
||||
## 4. Changes decided during the walk
|
||||
|
||||
### 4.1 The permission manager, rebuilt around the game's real state (D160–D163)
|
||||
|
||||
What exists: a desired-state mirror. The site pushes the set it authored, the plugin reports `foreign` holders
|
||||
only for names the site claims (`buildDesired` → `managed`), and `rust_perm_catalogue` holds just
|
||||
`(server_id, permission, seen_at)` — no owner, no holders, no groups.
|
||||
|
||||
What it becomes:
|
||||
|
||||
- **An inventory read** — a new plugin verb returning every registered permission *with the plugin that
|
||||
registered it*, every group with its title, rank, parent and members, and what each player holds directly
|
||||
and through groups. The walk showed why the owner must come from the registration, not the name:
|
||||
PermissionsManager files `zonemanager.ignoreflag.nokits` under Kits.
|
||||
- **The first import** — on first contact with a server, everything the inventory reports becomes site-owned
|
||||
(D160), so a server brought under the site keeps what it had.
|
||||
- **In-game changes** — per D161: auto-adopt by default, or revoke, or adopt by hand. The existing
|
||||
Revoke / Adopt answers stay for the two manual policies.
|
||||
- **The screen** (D162, D163, U-1) — players ⇄ groups → subject → plugin → permissions with Granted / Revoked;
|
||||
each toggle shows its state on each server (granted · waiting for a first connection · unresolved · not
|
||||
landed); subjects named by website account and in-game name or Steam id.
|
||||
- **The plugin-load signal** (F8), so the inventory and unresolved grants move when a plugin loads.
|
||||
- **Open for the plan:** ZoneManager's `zonemanager.ignoreflag.*` permissions exempt players from zone flags
|
||||
(§4.4). Under D160 the site owns those too — say how the screen presents them.
|
||||
|
||||
### 4.2 The kit-weekend template (D164)
|
||||
|
||||
`core.lease` on `<server>/default/kits.<kit>` plus `rust.kit.entitle` to everyone, authored together. The lease
|
||||
form reads the kit's `MaximumUses` and `Cooldown` and warns: "N linked players have already used this kit".
|
||||
|
||||
### 4.3 The event step editor (U-3–U-6, F11)
|
||||
|
||||
Pick an action or a lease by its label, and the step becomes that thing's own form: pickers for server, group,
|
||||
permission, monument, kit; toggles for yes/no; the limit shown beside minutes. No type tags, no ids, examples
|
||||
from the chosen lease. A phase that holds a timed step defaults to lasting that long, or says plainly that it
|
||||
won't. Start warns about unpublished changes. `rust.announce` already takes `delivery: popup` (phase 17) —
|
||||
show it as a Chat / Popup choice, and consider popups for the other player-facing event messages (a zone
|
||||
entered, a reward earned).
|
||||
|
||||
### 4.4 Zones: ZoneManager's options, and a dome (D166, D167)
|
||||
|
||||
- **Options.** ZoneManager 3.1.14 takes key/value arguments to `CreateOrUpdateZone`: settings (name, radius,
|
||||
size, rotation, enter and leave messages, radiation, comfort, temperature, safe zone, permission, parent, eject
|
||||
spawns) and 64 flags — vehicles (`NoVehicleMounting`, `NoVehicleDismounting`, `KeepVehiclesIn`,
|
||||
`KeepVehiclesOut`), combat (`PvpGod`, `PveGod`, `NoPve`, `NoFallDamage`), building (`NoBuild`, `NoDecay`,
|
||||
`UnDestr`, `NoUpgrade`), loot, NPCs (`NoNPCSpawns`, `NpcFreeze`), comms (`NoChat`, `NoVoice`) and more. The
|
||||
plugin reports the installed ZoneManager's flag list at hello; the form groups them and offers presets
|
||||
("Arena"). **There is no flying flag** — "allow flying in the zone" needs another plugin or a D168 helper.
|
||||
- **Domes.** ZoneDomes exposes `AddNewDome(player, zoneId, type, stack)` and `RemoveExistingDome(player, zoneId)`.
|
||||
Three things the walk established: its default sphere (type 0, one layer) is invisible at noon, and red at
|
||||
three layers showed only a band near the ground — choose a default by looking at each type on the rig; its
|
||||
domes are saved to its own data file and **outlive the zone** unless the bridge removes them at teardown and
|
||||
at expiry; and after a restart it loads before the bridge re-creates the zone, so the bridge must re-add the
|
||||
dome. Check that a null `player` is safe (it is used for messages only).
|
||||
- F12 and F13 land in the same code.
|
||||
|
||||
### 4.5 The live map (D165)
|
||||
|
||||
A per-type marker setting for staff, defaulting to the major monuments. Decide in the plan whether the plugin's
|
||||
monument sweep or the site does the filtering; the type (`monument_substation`, cave, …) is already in the
|
||||
monument data.
|
||||
|
||||
### 4.6 Chat titles: more conditions
|
||||
|
||||
The org lead's list, as inspiration (the names are examples): animal, bow, melee, blade, revolver, NPC, APC and
|
||||
helicopter kills; headshots; players killed; PvP and PvE kill distance; wood, ore and plants gathered; clothes
|
||||
and weapons crafted; structures built and repaired; players healed; rockets fired; explosives thrown; quests
|
||||
completed. Most need new counters in the plugin — the weapon class on a kill, headshots, crafting by category,
|
||||
heals, building and repair, explosives — each a hook, a tally field and a leaderboard column. D159's gathering
|
||||
counters feed the gathering titles. Quests need a quest plugin, and none is installed. The plan picks the first
|
||||
set; the rest follow.
|
||||
|
||||
### 4.7 NPCs
|
||||
|
||||
Research before deciding: which free uMod NPC plugins are maintained and expose spawning with a loadout, a
|
||||
name and a behaviour, against extending `rust.npc.place` to dress the stock scientist from a Kits kit and give it
|
||||
a display name. The goal the org lead named is server customisation — NPCs with different kits and names.
|
||||
|
||||
### 4.8 Steam sign-in (website, not this module)
|
||||
|
||||
Steam as a provider beside Google and Discord. It is OpenID 2.0, not OAuth2/OIDC, so it needs its own adapter.
|
||||
Leaning toward both halves: link-only sign-in (SSO never provisions an account), and linking Steam also creates
|
||||
the Rust link, since it proves the Steam id more strongly than a code does. Belongs in `website/` with its own
|
||||
plan; noted here because it changes R1's identity story.
|
||||
|
||||
## 5. Protocol
|
||||
|
||||
One bump, **protocol 13**, carries every wire change here, so the plugin, sidecar, module and PROTOCOL.md move
|
||||
once:
|
||||
|
||||
- `world.expired` carries `what` (F13).
|
||||
- The configuration reload outcome as an asynchronous frame (F9).
|
||||
- A plugin-loaded / unloaded frame (F8).
|
||||
- The permission inventory verb and its reply (§4.1).
|
||||
- ZoneManager's flags at hello, zone options on `world.zone`, the dome option (§4.4).
|
||||
- New tally fields for D159 and the first title counters (§4.6).
|
||||
|
||||
F15 changes no message shape and ships ahead of the bump.
|
||||
|
||||
## 6. Order, and what gates the cutover
|
||||
|
||||
1. **Before anything else:** F15 (data corruption), and F9 + F10 (it throws away edits). Small, no protocol change
|
||||
for F15.
|
||||
2. **Protocol 13 with the remaining fixes:** F13, F12, F1, F3, F8, F7, F2, F4, and F5/F6 in the module.
|
||||
3. **The redesigns** (§4.1, §4.3, §4.4) — each its own phase, planned in detail before code.
|
||||
|
||||
**Recommended gate:** steps 1 and 2 land before Module-Rust's cutover (phase 19); the redesigns follow it.
|
||||
Nobody outside the org runs module-rust yet, so the cutover should not carry known corruption or silent
|
||||
rollbacks, but it need not wait for the new screens. Open for the org lead.
|
||||
|
||||
## 7. Helper plugins (D168)
|
||||
|
||||
Where the walk already points at one:
|
||||
|
||||
- **ZoneManager** — re-evaluating who is inside a zone the bridge just created or restored (F12), if it has no API
|
||||
for it; and a flying permission per zone (§4.4).
|
||||
- **ZoneDomes** — only if a null `player` turns out to be unsafe in its API.
|
||||
- **Kits** — none needed: D164 uses the existing credit path.
|
||||
|
||||
A helper is optional, versioned and released with the bridge, detected at hello, and does one job. The bridge
|
||||
never depends on one to load.
|
||||
|
||||
## 8. The re-walk
|
||||
|
||||
After step 2 of §6, on both frameworks:
|
||||
|
||||
- The whole player walk again, adding: a line with é, — and an emoji through announce and a config save (F15); a
|
||||
configuration save that needs a cold compile (F9); wood from a felled tree and picked-up hemp (F1); your own
|
||||
wall (F3); a code redeemed with a server down (F5, F6).
|
||||
- A zone restarted with a player standing in it, and a zone opened around a player (F12).
|
||||
- A zone left to expire, checked by `kind=world.expired` (F13).
|
||||
- A plugin unloaded, a grant made, the plugin loaded again — the grant lands within a minute (F8).
|
||||
- Then the steps still owed: the Carbon subset, player step 8 and the map walk with a second player, events step
|
||||
7 with several players, the phone walks.
|
||||
|
||||
## 9. Open questions for the org lead
|
||||
|
||||
1. The cutover gate in §6 — fixes before phase 19, redesigns after?
|
||||
2. F14 — should ingest mark an expired zone `expired` (recommended), or keep D96's "maps it to nothing"?
|
||||
3. Steam sign-in (§4.8) — both halves, and does it belong to this workstream or to `website/`?
|
||||
4. Which title conditions form the first set (§4.6)?
|
||||
Reference in New Issue
Block a user