veratown-prototype

World Administration (Locations, Map, Game Config)

This guide documents the CRUD command suite that manages runtime world data in MongoDB through transport-neutral services and repositories. The separate web administration workspace also manages stored configuration with its own web identity, explicit write opt-in, concurrency checks and audit history. Its map is the effective stored creation map, never a replacement for live BC observations. Live capture (world map save) remains a bot-only operation. The feature configuration catalog lists all feature configuration owners, startup defaults, and command sequences.

Runtime configuration reporting

Room-scoped runtime heartbeats expose actual consumer receipts in the web recovery runtime panel, not an inferred consequence of an administrative save. GameConfigRuntime.apply() reports the revision/time installed in the shared cache only. It does not prove any game or session has adopted that revision. Aliases are separately pending until the next alias/help lookup replaces their lazy cache; validation errors report a fixed identifier and leave the prior successful receipt visible while aliases fail closed.

The serialized room-template reload reports only after installing the new creation definition. Its revision remains unknown because this projection has no authoritative aggregate revision. It affects the next missing-room creation, never the existing room. A failure still disables creation; the last-loaded receipt remains historical. Watch/load errors use fixed identifiers rather than messages or configuration content. Running door/location replacements are reported separately by the door plugin, also without an invented aggregate revision. Casino, shop, Location Entry Behavior and shower also publish bounded feature receipts; their guides describe the exact interaction/session coverage. Truth/Dare, Hot Seat, Dilemma and Anonymous Whisperer report a dedicated configuration revision only after a new active session is successfully created. Those receipts do not infer that a revision came from defaults, or describe every active session. Appearance reports a validated itemset selected for an application attempt, without claiming that BC observed it; itemset revisions are not aggregated. A helper worker reports readiness only after identity preparation and settings load, but those settings have no revision or default provenance; supervisor task handling remains unknown. The runtime view compares only consumers using the same process-local shared-config revision. Casino and interaction-driven feature changes do not rewrite every existing session. Uninstrumented consumers remain unknown.

Older heartbeats without consumer receipts remain readable and report unknown. Process freshness is displayed independently; even recent successful receipts are not live BC observations.

Responsibilities

Room admins also manage the opt-in shower feature’s room-scoped settings and song catalog. Runtime behavior and the dedicated-account qualification gate are documented in the shower system guide.

The BC adapter lives in src/features/world/commands/world-admin-command-suite.ts; shared rules stay in feature services so future channel adapters (for example Discord) can call the same use cases with channel-specific authorization.

Commands

All commands require room-admin access and reply by private whisper. Permissions are checked again for every guided answer/control and before completion; revoking admin access cancels the active session without a write. Long replies are split into ordered whispers of at most 1,800 characters, preserving lines and Unicode characters where possible rather than failing BC’s message-length guard.

World command descriptors are included in shared help only for a current room admin. Non-admins receive the same neutral private response for /bot world help as for an unknown world scope; guided-session prompts and command execution continue to enforce room-admin authorization independently.

Use native /bot <command> or bang-prefixed !<command>. For example:

/bot world config set
/bot world answer game.speed
/bot world answer 2
/bot world alias add spin casino slots fixedArgs=10
/bot world alias list
/bot world shower show

The shower feature starts disabled and has no seeded songs. Add only administrator-provided original or public-domain text; song text is not shown by world shower song list. A location must be an enabled point with type shower. Runtime clothing changes require a positive BC wardrobe permission result and accept matching BC room updates as sufficient observation, without independent helper corroboration; see the shower guide before enabling it.

Quote two-word alias names, for example /bot world alias add "red bet" casino roulette bet. Alias targets must be registered help command paths; sensitive targets are rejected. Admin-only targets are allowed, but the target command still performs its normal permission check. Invalid aliases receive a reply that identifies the rejected rule or target. fixedArgs is inserted before the arguments supplied by the player. Aliases can be invoked with either !<alias> or native /bot <alias> syntax. The parser routes real command paths first, performs only one alias expansion, and applies the target’s ordinary permissions, location checks, and rate limits.

The room-scoped command.aliases key is seeded with bet → casino roulette bet, slots → casino slots, and balance → casino balance only when absent. Updates are validated against the live help catalog, revision-checked, and applied through the existing prototypeGameConfig change stream. Removing the key disables aliases until the next startup re-seeds the starter set. Scoped help lists shortcuts only beside currently visible target commands; fixed argument values are not displayed. A target removed from the live command catalog becomes unknown without disabling other aliases.

Each guided flow asks one question at a time. Reply with /bot world answer <text>; the final answer saves automatically. world back revisits the previous answer. world skip is available only for optional steps: it keeps the current value when editing, or leaves an optional field unset when creating. world cancel discards the session. Starting another flow replaces the previous session; sessions expire after five minutes of inactivity.

Location edits accept none to clear position, label, or description. Map fog accepts yes (enable), no (disable), or clear (remove the setting). Configuration keeps the existing global scope and adds explicit room scopes; a room lookup never falls back to global settings. The singleton prototypeGameConfig active document uses optimistic revision checks. Every successful update after the initial write transactionally stores the replaced revision as a backup:<revision> document in the same collection; a conflict or failed backup leaves the active configuration unchanged. Backups have no automatic pruning or TTL and are not included in the configuration-copy allowlist. These writes require MongoDB transaction support (a replica set). Each scope is limited to 200 keys; structured values are bounded JSON (16 KiB per value, 256 KiB total document, depth 8, bounded arrays/objects). Plain text remains limited to 500 bytes. Feature consumers validate their own strict, versioned schemas before using a stored value. Never enter passwords, access codes, or other secrets.

For example, create a point location with type game, then bind its key through the casino rules value. The current guided location command does not create region geometry; an enabled roulette region must be operator-defined in veratownLocations before binding. The game remains unavailable unless the main bot also observes the sender inside the enabled location:

/bot world config set room main casino.rules {"schemaVersion":1,"entryGrant":{"chips":20,"intervalMs":86400000},"locations":{"slots":[{"key":"casino-slots","shape":"point"}],"roulette":[{"key":"casino-floor","shape":"region"}]},"slots":{"symbols":["🍒","🍏","🍌","🍑","💎","7️⃣"],"weights":[35,25,18,12,8,2],"fourKindQuarterUnits":[4,4,4,4,400,2000],"threeKindQuarterUnits":[4,4,4,4,60,200],"twoPairsQuarterUnits":5,"pairQuarterUnits":4,"fourFruitQuarterUnits":4,"bettingWindowMs":10000,"resultWindowMs":5000,"renewalWindowMs":5000,"maxPlayers":20,"maxWager":100},"roulette":{"payouts":{"straightUp":36,"split":18,"street":12,"trio":12,"corner":9,"fourNumber":9,"sixLine":6,"evenMoney":2,"dozen":3,"column":3},"bettingWindowMs":45000,"resultWindowMs":10000,"renewalWindowMs":5000,"maxPlayers":20,"maxWagers":1000,"maxWager":100}}
/bot world config show room main

The write reply and subsequent show report the active document revision. Casino-specific fields, supported games, payout ceilings, slot return, timing, participant/wager limits, and location shapes are validated before an admin write is persisted. An invalid or global casino.rules write is rejected without changing the current revision. Valid room config changes apply live; a started game round retains its saved rules snapshot and revision.

Runtime update behavior

Map revision workflow

Map sign preservation

The shared mapDataSchema validates live saves, selected stored maps, revision and backup reads/writes, configuration copies, and missing-room templates. Its optional CellData field is a plain record with at most 1,600 entries:

Signs survive save, metadata edit, backup, both restore forms, template refresh, and missing-room creation. These operations do not apply stored maps to an existing live room. Invalid selected heads, revisions, and backups fail explicitly; the reader never skips a corrupt head to use an older revision or legacy fallback. Validation replies expose bounded schema fields/cell indices only, never sign text. Sign configuration is authorized map data, not captured chat; do not log, journal, or echo its contents. There is no new sign-editing command or storage migration.

Before deploying, obtain separate approval for a read-only existing-sign audit. Report only counts and lengths, not content. Stop rollout for signs above the 150-code-unit policy and resolve the conflict explicitly. Live Unicode rendering, save/restore, room creation, door updates, and reconnect still require separately approved qualification on the actual BC version. Offline tests are not that evidence.

On 2026-10-15, the operator reported that all of these checks passed on R133Beta2 in test context “Personal Commit”: browser/server version, Unicode/newline sign rendering, live save and stored restore, missing-room creation, unrelated door updates, reconnect, and the existing-sign length audit. The exact build and room/environment were not supplied, and the assistant did not independently observe the run. This is not deployment approval or qualification of unrelated features. Confirm that the report applies to the intended build and target before release; the dated archived proposal retains the evidence and its limitations. The current source pin is R133; this historical report does not qualify the updated client behavior.

flowchart LR
    BC["Pinned BC declarations + observed MapData"] --> Schema["Shared strict mapDataSchema"]
    Admin["WorldAdminCommandSuite"] --> Service["MapAdminService"]
    Service --> Schema
    Service --> Repo["MongoMapAdminRepository"]
    Repo --> Revisions[("Append-only map revisions")]
    Repo --> Backups[("Map backups")]
    Repo --> Reader["Validated effective-map reader"]
    Reader --> Template["Missing-room creation template"]
    Door["Guarded SetMapObjectAction"] --> BC
    Door -. "preserves unrelated CellData" .-> BC

The schema treats sign CellData as validated configuration, not chat or live state. Save validates the server-observed map before append; metadata edits and restores carry the complete validated map forward. Door mutations preserve unrelated map cells and observed state changes only on inbound room sync.

Older code can silently discard signs. Before rollback, suspend map save, edit, backup, and room recreation; retain the new documents unchanged. Previously discarded text cannot be recovered from those old revisions.

Teleport-pad configuration preservation

At source pin 51df6acc01f8fa185079d8deebf591fe3642a148 (still R133), map CellData also accepts { Type: "Teleporter" } with optional:

Destination absence is valid. No defaults, automatic pairing, destination walkability checks, or browser teleport callbacks are applied by the bot. Dormant cell configuration remains intact regardless of the object at that index. All entries must validate before saving, restoring, copying, or creating a room; invalid fields reject the entire operation with redacted diagnostics.

Sign and teleporter entries coexist and survive the same revision/backup and room-creation flow shown above. Guarded unrelated door updates preserve them. The bot does not infer a live move from a configured destination. Qualify pad appearance and native movement separately on the intended BC build; offline preservation tests do not certify the browser behavior.

Older sign-only validators reject teleporter-bearing documents. Before rollback, suspend map administration and room recreation, retain backups, and resolve compatibility explicitly rather than stripping pad configurations. See the 2026-10-22 source review.

The current source-pinned map catalog contains 372 objects and retains upstream DeprecatedID replacement references, editor-only PaletteImage labels, and the CanBeTetherPoint capability flag. These are catalog metadata only: the bot does not migrate stored map cells, execute BC editor callbacks, or manage tethers. Previous R133 category-specific Blank door references remain valid and retain their former numeric IDs; the current map catalog represents those cells as EmptySpace/Passable. See the 2026-11-03 source review. The deprecated EmptySpace/Passable aliases all point to canonical map object ID 100; style/type lookups select that canonical entry. Other ambiguous map styles still require an explicit type or are rejected.

/bot world map save
/bot world map revisions
/bot world map show
/bot world map restore 1

save requires a connected, synchronized bot in its configured room. It clones only the validated BC-observed MapData; stale/disconnected snapshots, another room, missing maps, and malformed 40x40 maps are rejected without a database fallback. Current objects include temporarily open doors: close doors before saving if the stored creation map should show them closed.

The first save is revision 1. Every save/edit/restore inserts a new document with a higher revision; existing documents are never overwritten. Restoring revision 1 when revision 3 is current creates revision 4 with restoredFromRevision: 1. Backups still snapshot stored map data, not the live room; backup restore also appends a revision. The old restore <backup-id> spelling now gives guidance to use restore-backup; numeric restore arguments refer only to revision numbers.

Opening or cancelling an edit is read-only. Edit drafts retain the selected revision: if another writer advances it before completion, nothing is written and the admin is asked to restart the flow. A partial unique (roomKey, revision) index excludes legacy documents and rejects concurrent revision allocation; there are no blind retries. A lost insert response is reconciled by operation identity before reporting success or conflict.

Without revision documents, legacy main, then current, then the room-template map remains the fallback (main-room scope only). Legacy documents need no backfill and are preserved. A corrupt/duplicate highest revision fails explicitly rather than silently choosing an older revision. Failed template reloads disable missing-room creation until a valid reload or restart; they never mutate the observed room. If a write persisted but refresh failed, the reply distinguishes that outcome and warns against repeating the save.

flowchart LR
    BC[BcClient current-connection map observation] --> Service[MapAdminService]
    Commands[WorldAdminCommandSuite] --> Service
    Service --> Port[MapAdminRepository port]
    Port --> Mongo[MongoMapAdminRepository append-only revisions]
    Mongo --> Reader[Shared effective-map reader]
    Reader --> Template[Missing-room creation template]
    Mongo --> Watch[WorldAdminPlugin owns map/room watchers]
    Watch --> Reader
    LocationAPI[Core LocationAdministration API] --> Commands

Future Discord adapters reuse these services and transport-neutral actor IDs, but must independently check guild/role permissions. No Discord dependency or adapter is introduced here.

Collections

The configuration-copy allowlist is unchanged. Revision documents are validated before 1:1 upsert; IDs, room scope and revision numbers are not remapped. Destination-only history remains intact; conflicting revisions fail against the unique index. Review the dry run before --apply, especially when copying between databases that already have independent histories.