fix(rust): protocol 13 step 2 — expiry, plugin loads, the loading hold, NPC names, the link fleet (F2 F5 F6 F7 F8 F13 F14)
The module's half of PLAN_FIXES §6 step 2 (decisions D181-D185, docs#288). - F13/F14 (D170, D183): `world.expired`, recognisable from protocol 13 by its `what`, is handed to core as the resource the zone step ledgered (`world`, `<serverId>:<id>`) through ctx.events.expired, which records it `expired`. coreApi moves to ^1.11.0 (website#209). - F8 (D184): `plugin.loaded` / `plugin.unloaded` mark the permission sync dirty when the plugin added or removed permissions, so an unresolved grant lands on the next tick instead of the fifteen-minute audit. - Catalogue: plugin.loaded/unloaded, world.expired and lease.expired are staff kinds. The last two were never classified (default deny kept them off public pages); the test now covers every event kind through protocol 13. - F7: permission and title pushes hold while the stored hello says `worldReady: false` (a human's "sync now" does not); a failed or refused permission sync now logs at warn. - F2 (D185): the killfeed names an NPC attacker — a family (Scientist, Bandit guard, Bradley APC…) or the prefab without its variant digits (wolf2 → Wolf). - F5/F6: a link code is asked of the servers that minted one in the last six minutes first, then of the rest, each group in parallel; "unsure" only when one of the minting servers is unreachable. - D182: the admin server list carries the ZoneManager helper's state from the hello, and the servers page says what a missing or failed helper costs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
This commit is contained in:
@@ -38,6 +38,7 @@ const configDb = require('./model/config/config.db')
|
||||
const configModel = require('./model/config/config.model')
|
||||
const db = require('./model/events/events.db')
|
||||
const engagement = require('./engagement/emit')
|
||||
const eventWorld = require('./eventWorld')
|
||||
const links = require('./model/links/links.model')
|
||||
const permissionsDb = require('./model/permissions/permissions.db')
|
||||
const sidecar = require('./sidecarClient')
|
||||
@@ -201,6 +202,29 @@ async function apply(serverId, item, server = null) {
|
||||
await permissionsDb.markDirty(serverId)
|
||||
break
|
||||
|
||||
// ── Protocol 13: a plugin loaded or unloaded (F8, D184) ─────────────────
|
||||
//
|
||||
// A grant for a plugin that was not loaded stays `unresolved` until that
|
||||
// plugin comes back, and the first walk watched one land thirteen minutes
|
||||
// late, on the fifteen-minute audit. The frame carries the permissions the
|
||||
// plugin added or removed, and only a non-empty list is a reason to sync —
|
||||
// a plugin that registers nothing cannot have changed what a grant resolves
|
||||
// to. `perm.drift`'s posture: a reason, and the next tick (30 s) is the answer.
|
||||
case 'plugin.loaded':
|
||||
case 'plugin.unloaded':
|
||||
if (Array.isArray(frame.permissions) && frame.permissions.length > 0) {
|
||||
await permissionsDb.markDirty(serverId)
|
||||
}
|
||||
break
|
||||
|
||||
// ── Protocol 13: a zone reached its deadline (F13, F14, D170, D183) ──────
|
||||
//
|
||||
// Core records the run's resource row as `expired`. Not awaited: it is
|
||||
// core's bookkeeping, fire-and-forget by contract.
|
||||
case 'world.expired':
|
||||
eventWorld.expired(serverId, frame)
|
||||
break
|
||||
|
||||
// ── Protocol 13: how a configuration save's reload ended (F9, D179) ─────
|
||||
//
|
||||
// The save was answered before the reload finished and recorded as
|
||||
|
||||
Reference in New Issue
Block a user