docs(modules): second contract pass over MODULE_API.md — restores a dropped reconcile, reprices R9 #250
Reference in New Issue
Block a user
No description provided.
Delete Branch "docs/rust-plan-contract-pass2"
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
Follow-up to #249. §7 of the plan audited it against the Integration Kit and the template; this pass reads
MODULE_API.mditself, enumerating every member rather than grepping for registration names.It found four things. Adds §11 and wires the consequences into phases 1, 13 and 14.
1. A regression:
reconcilehad been droppedctx.events.reconcile()and an action'sreconcile()appear nowhere in the merged plan. The twelve-phase first draft had them — "phase 6: reconcile, and the boot-id watch" — and the rewrite to twenty phases lost them. That is a regression in the plan, not a decision.It matters more for Rust than for the game the contract was written against. The kit rates
reconcilethe one omission that is "merely a lower standard rather than a broken promise" — but that assumes a world which persists. Rust wipes monthly and a wipe invalidates every ledgered resource for that server at once, and core cannot tell a wedged sidecar from a game that rebooted and lost everything: it sees{ ok: false, retry: true }either way. It asks once at its own boot and otherwise waits to be told.ctx.events.reconcile()is being told, and its trigger is a watch on the game's boot id changing — which is also the only way to tell a game restart from a sidecar reconnect.Restored to phase 13.
2. R9 was mispriced — the visibility framework is
module-uo's, not core'sR9 says the map's per-layer switches work "through the existing visibility framework", which reads as reuse. It is not reuse. §6.3 records
shardVisibilityas module-owned, and the tree confirms it — the util, both models, the admin controller and its tests all live undermodule-uo/server/, and there is nothing by that name left inwebsite/server.§2.7 forbids a module requiring anything outside its own directory, so
module-rustcannot import a line of it and builds its own. Not a reason to change the decision — per-layer switches are still right — but phase 14 now carries a visibility layer of its own rather than a configuration of somebody else's.3. A missing declaration:
extensionsR13 claims two extension slots and never says where they are declared.
module.jsonhas anextensionsarray (§2.1), and the dry run's own manifest carried"extensions": ["admin.users.detail"]. Likemounts, it is a statement of surface the loader holds against reality. Phase 1 adds it.4. The
ctxmembers the plan had never namedctxhas 29 members (§2.3); the plan named a handful. The ones that change work:ctx.secretBoxctx.middleware.rateLimitctx.uploadsctx.activity.logctx.teams.publish/.activity.push/.reconcilectx.postsregisterAnnounceLegandregisterPostHookAlso recorded: §6.8, a constraint on phase 10 and on purge.
engagement_rules.trigger_idis a plainVARCHARwith no FK and no cascade, so a module can be removed and reinstalled without destroying an operator's rules — and a rule whose trigger or audience is unregistered shows dormant, never an error and never auto-deleted. An audience resolving to the empty set is not the same answer as "resolved to nobody". The failure that prevents is exact: an id that stops resolving must never silently become a send to a different set of people.Plus the two client lists in full (
registryandui), since §7 said "UI kit discipline" without saying what is in it; and one confirmation for R10 —/api/v1/public/modulesreturns onlystartedmodules with no state and no failure reason, so a Rust module that failed to boot makes the app render a site without those screens rather than one advertising screens that503.How it was tested
Documentation only. Every claim checked against a source in this pass:
ctx's 29 members,module.json's 11 fields, theregistryanduimember lists, and §2.9's response shape — all read out ofMODULE_API.md§2.1, §2.3, §2.9, §3.3 and §3.4.shardVisibility's location —findover both trees: six files undermodule-uo/server/, none underwebsite/server/.ctx.events.reconcilein the merged plan —grepoverPLAN.md, which is how the regression was found.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