veratown-prototype

Feature Configuration And Startup Defaults

This guide inventories the configuration consumed by each implemented feature, where it is stored, what startup initializes, and the available operator command flows. Runtime configuration is read only from the isolated database selected by RUNTIME_TARGET; source-database access remains restricted to the allowlisted, read-only copy script.

Per-container composition and supported runtime capabilities can additionally be supplied by a typed, versioned bot-instance profile in the selected runtime database. BOT_INSTANCE_ID selects that profile after database connection; the profile role overrides RUNTIME_ROLE without changing the static plugin wiring. Bootstrap settings, BC credentials, and observation tokens remain outside the profile; its runtime target is recorded only as scope metadata for isolation checks. See the bot profile wizard.

Ownership And Defaulting

Feature Configuration authority Startup behavior
World map and doors veratownRooms, veratownMap, prototypeMapBackups, veratownLocations, keypadDoorDefinitions, keypadGroupDefinitions, keypadGroupMemberships; optional DOOR_DEBUG diagnostics Loads validated room-specific data. Seeds missing room-wide live admin/whitelist groups with public default code knock; preserves edits. No map coordinates, doors, locations, or memberships are invented.
BC room settings prototypeRoomConfig; legacy veratownRooms settings are used only when no versioned settings exist Admin-Map appends settings revisions. On supervisor startup, missing versioned settings are imported from the synchronized BC room; otherwise the latest revision is applied and verified against room sync. Room name and map data remain separate.
Casino prototypeGameConfig active document _id: "main", key rooms.main["casino.rules"]; roulette helper identities/templates in the existing Helper Bots collections Inserts the validated baseline below only when that room-scoped key is absent. A stored value is never replaced. Empty game-location bindings deny location access; roulette presentation defaults to whisper.
Shop region prototypeGameConfig active document _id: "main", key rooms.main["shop.rules"]; orders in prototypeShopOrders; appearance itemsets in prototypeItemSets Inserts default drink/favor offers only when absent. The shop region and itemset favor definitions are operator-managed; releases and favors require adult-policy confirmation.
Command aliases prototypeGameConfig active document _id: "main", key rooms.main["command.aliases"] Seeds the bet, slots, and balance shortcuts only when absent. Room admins can manage aliases live with world alias; player-defined aliases are unsupported.
Truth or Dare prototypePartyGameConfigs document _id: "<roomKey>:truth-dare" and immutable revisions in prototypeTruthDarePrompts Inserts a missing disabled config and ten approved English prompts. The code release gate is approved; room activation and player opt-in remain required.
Hot Seat prototypePartyGameConfigs record <roomKey>:hot-seat; operator-managed prototypeHotSeatPrompts Inserts a missing disabled config and ten approved English prompts. Preserves admin settings and moderation edits; writes use expected revisions.
Staged Table prototypePartyGameConfigs record <roomKey>:staged-table; immutable revisions in prototypeStagedTablePrompts; sessions in prototypeStagedTableSessions; optional stage sets in prototypeItemSets Inserts a disabled, unconfirmed config and ten approved English prompts. The dry-run-first party-game provisioner also seeds six validated strip-only stage itemsets if absent. Appearance requires a configured release set, a pinned plan, and per-player opt-in.
Anonymous Whisperer prototypePartyGameConfigs record <roomKey>:anonymous-whisperer; prototypeWhispererPrompts Inserts a missing disabled config and ten enabled prompts; explicit adults-only confirmation is required to activate.
Appearance prototypeItemSets The shared itemset schema supports bounded conditional variants selected from observed body traits or BC prerequisites; fixed-set feature policies reject variants. The party-game provisioner seeds only six validated Staged Table stage itemsets if absent; runtime access is read-only.
Shower system prototypeShowerConfig, prototypeShowerSongs, and prototypeShowerSongCounts; shower coordinates remain in veratownLocations Inserts no enabled config or songs. Room-admin commands manage bounded settings and song text; matching BC room updates are sufficient observation, helpers are optional, and explicit wardrobe permission is required.
Location Entry Behavior prototypeGameConfig key rooms.main["location-entry-behavior.rules"], standard prototypeItemSets, and veratownLocations Inserts a disabled generic baseline only when neither the generic nor legacy room-scoped key exists. No location-entry-specific itemset or location is seeded; itemset timer settings pass through to BC.
ABCL Region Feature prototypeGameConfig key rooms.main["abcl.rules"]; prototypeAbclConsents; minimized prototypeAbclObservations and prototypeAbclSignals; ABCL helper tasks in prototypeHelperTasks; shared appearance mutation leases No default is inserted. ABCL runs in the supervisor and remains inactive unless the value is valid, enabled, adults-only-confirmed, and references an enabled region and registered abcl helper; invalid ABCL configuration does not block supervisor startup.
Emergency Release Enabled emergency.release.clothing record in prototypeItemSets Seeds no appearance set; the native command applies the configured set directly to the requesting member.
Dilemma prototypePartyGameConfigs keyed by (roomKey, gameId) and prototypeDilemmaPrompts Inserts a missing disabled config and ten active English fictional A/B prompts. Adult-policy confirmation and explicit activation remain required.
Trick-or-Treat prototypePartyGameConfigs record <roomKey>:trick-or-treat; enabled references in veratownLocations and keypadDoorDefinitions; sessions in prototypeTrickOrTreatSessions Inserts a missing disabled config only. Admin Web validates selected checkpoints and emote doors, and pins costume/consequence itemset revisions; player sessions are never seeded.
Communication prototypeGameConfig global key settings["motd.schedule"]; MOTD_TEXT fallback; BC-observed friend state Uses the first matching weekday/time rule and preset, falling back to MOTD_TEXT when the schedule is absent, invalid, or unmatched. Friend reciprocity has no Mongo feature configuration.
Prototype status No feature configuration document Reports runtime/connection status only.

Casino wallets, ledgers, sessions, shop orders, Truth/Dare, Dilemma, Hot Seat, and Trick-or-Treat sessions, action journals, and process heartbeats are runtime state, not feature configuration. They are not initialized with player data or copied from the source database.

Party-game baselines and activation

Startup seeds the main room only. Each feature owns its strict default builder and Mongo writes; shared infrastructure does not own game rules or prompt text. Seeds use _id-scoped $setOnInsert, preserving enabled state, existing operator settings, prompt revisions, and moderation decisions. Invalid existing records are not repaired or replaced silently. Each starter catalog contains ten non-explicit, reviewed English prompts; Truth/Dare supplies five truths and five chat-only dares, Staged Table supplies fictional prompts, and Dilemma supplies ten fictional A/B choices.

New configs remain disabled with no implied adults-only attestation. The provisioning workflow prints a read-only plan, validates the five prompt-based configurations and catalogs before writes, and requires explicit --enable --confirm-adults-only --apply for activation. At least ten usable prompts per game are required by this tool. Existing config activation uses revision compare-and-set; all other settings are preserved. Re-running provisioning does not advance unchanged revisions. The tool does not create player accounts, change balances, or migrate sessions.

Shop Defaults

Startup inserts shop.rules into the explicit main room scope only when the key is absent. The default enables the featureโ€™s offer list and ordinary drink purchases, but leaves the adult-policy confirmation false and release purchases disabled. The shopโ€™s distinct shop region and itemset favor definitions are operator-managed and are never seeded. Invalid stored rules fail closed.

Use the shop guide for region creation, safe adult policy configuration, offers, and release/favor operation.

Casino Baseline

At startup, the composition root calls the game-config repositoryโ€™s insert-if-absent operation for casino.rules in the explicit main room scope, then loads the resulting document into GameConfigRuntime. Seeding is revision-checked and retried on concurrent writes. Existing global settings, room settings, and operator-supplied casino.rules values are preserved. An invalid existing value is not silently repaired; it fails closed when consumed. Startup logs whether the baseline was inserted or already existed and reports only the room key and document revision.

The exact baseline values are:

Setting Default
schemaVersion 1
entryGrant.chips 20
entryGrant.intervalMs 86400000 (24 hours, rolling)
locations.slots and locations.roulette Empty arrays; no player has game-location access
slots.symbols ["๐Ÿ’","๐Ÿ","๐ŸŒ","๐Ÿ‘","๐Ÿ’Ž","7๏ธโƒฃ"]
slots.weights [35,25,18,12,8,2] (must total 100)
slots.fourKindQuarterUnits [4,4,4,4,400,2000]
slots.threeKindQuarterUnits [4,4,4,4,60,200]
slots.twoPairsQuarterUnits, pairQuarterUnits, fourFruitQuarterUnits 5, 4, 4
Slot betting/result/renewal windows 10000 / 5000 / 5000 ms
Slot maximum players/wager 20 / 100 chips
Roulette payouts Straight-up 36, split 18, street/trio 12, corner/four-number 9, six-line 6, even-money 2, dozen/column 3
Roulette betting/result/renewal windows 45000 / 10000 / 5000 ms
Roulette maximum players/wagers/wager 20 / 1000 / 100 chips
roulettePresentation.mode whisper; wheel_helper requires an enabled helper ID and reviewed opening/spinning Emote template IDs

The default entry grant is active on observed room entry and ready/reconnect, independently of the casino game gate. CASINO_GAMEPLAY_ENABLED is now true after operator qualification and approval on 2026-10-15; it is a code constant, not an environment variable. Seeding alone grants no game-location access: empty bindings still deny wagers. Game sessions continue to save their immutable rules snapshot and source revision.

Command alias baseline

Startup inserts the following enabled aliases in rooms.main["command.aliases"] only when the key is absent:

Name Target
bet casino roulette bet
slots casino slots
balance casino balance

The key is validated when written and parsed on every new game-config revision. Room admins manage aliases with world alias add|remove|list; generic room config writes are also validated against the live command-help catalog. Admin-only targets remain protected by their target handler. Aliases are a presentation and routing convenience only; they do not bypass permission, availability, or location checks.

Location Entry Behavior Baseline

At startup, after the casino baseline, the composition root seeds location-entry-behavior.rules in the explicit main room scope only when both that key and legacy bunny.rules are absent. Existing values and other game-config settings are preserved. Concurrent writes are retried; malformed existing values are not silently repaired. The generic baseline is:

{
    "schemaVersion": 1,
    "enabled": false,
    "locationTypes": {}
}

The generic key takes precedence when both keys are present. Legacy Bunny configuration remains readable, and removing the generic key while a legacy key exists does not seed a new baseline. prototypeGameConfig has one revision for the whole document; a seed advances that shared revision and transactionally backs up the prior revision. The disabled baseline has no behavior rules or itemset references, so seeding alone never sends messages or changes appearance.

Feature Configuration UML

classDiagram
    direction LR

    class RuntimeDatabase {
        <<isolated target database>>
    }
    class MongoMapRepository {
        locations
        doors
        groups
        memberships
    }
    class MongoGameConfigRepository {
        prototypeGameConfig
        transactional prior-revision backups
    }
    class GameConfigRuntime {
        explicit room scopes
        revisioned snapshots
    }
    class CasinoRulesConfig {
        entryGrant
        locations
        slots
        roulette
        roulettePresentation
    }
    class MongoAppearanceItemSetRepository {
        prototypeItemSets
    }
    class AppearanceItemSet {
        revision
        enabled
        ordered pieces
    }
    class MongoLocationEntryBehaviorRepository {
        prototypeGameConfig
        prototypeItemSets
    }
    class LocationEntryBehaviorConfig {
        enabled
        locationTypes
        itemSets
    }
    class HotSeatConfig {
        roomKey
        enabled=false when absent
        revisioned bounded settings
    }
    class HotSeatPrompt {
        moderation status
        content revision
        ten English starter prompts
    }
    class DilemmaRepository {
        prototypePartyGameConfigs
        prototypeDilemmaPrompts
        prototypeDilemmaSessions
    }
    class DilemmaConfig {
        enabled
        adultsOnlyRoomConfirmed
        bounded players, windows, quorum and rewards
    }
    class DilemmaPlugin {
        per-round opt-in
        deadline recovery
        idempotent shared-credit awards
    }
    class PrototypeConfig {
        MOTD_TEXT
        APPEARANCE_QUALIFICATION_ENABLED
    }
    class MotdService {
        +select scheduled preset or MOTD_TEXT fallback
    }
    class AppearancePlugin
    class CommunicationPlugin
    class PrototypeStatusPlugin

    RuntimeDatabase --> MongoMapRepository : operator-managed world data
    RuntimeDatabase --> MongoGameConfigRepository : supported config only
    GameConfigRuntime --> MongoGameConfigRepository : load and watch
    GameConfigRuntime --> CasinoRulesConfig : validate room scope main
    RuntimeDatabase --> MongoAppearanceItemSetRepository : operator itemsets
    MongoAppearanceItemSetRepository --> AppearanceItemSet : validate before use
    RuntimeDatabase --> MongoLocationEntryBehaviorRepository : location behavior policy and itemsets
    MongoLocationEntryBehaviorRepository --> LocationEntryBehaviorConfig : validate room policy
    MongoLocationEntryBehaviorRepository --> AppearanceItemSet : consume standard set
    GameConfigRuntime --> LocationEntryBehaviorConfig : validate explicit room scope main
    RuntimeDatabase --> HotSeatConfig : insert disabled default only when missing
    RuntimeDatabase --> HotSeatPrompt : insert missing approved starters; preserve edits
    RuntimeDatabase --> DilemmaRepository : room config, reviewed prompts and sessions
    DilemmaRepository --> DilemmaConfig : strict validation; insert missing disabled baseline
    DilemmaPlugin --> DilemmaRepository : recover active rounds
    GameConfigRuntime --> MotdService : global motd.schedule
    PrototypeConfig --> MotdService : MOTD_TEXT fallback
    MotdService --> CommunicationPlugin : whisper selected greeting
    PrototypeConfig --> AppearancePlugin : qualification gate

Configuration Flow UML

classDiagram
    direction LR

    class Startup {
        +main()
        +initializeRepositories()
    }
    class MongoGameConfigRepository {
        +setIfAbsent(key, value, roomKey)
        +load()
        +set(key, value, roomKey)
        +watch(reload, onError)
    }
    class GameConfigRuntime {
        +load()
        +current()
        +getForRoom(roomKey, key)
        +start()
        +stop()
    }
    class GameConfigAdminService {
        +show(roomKey)
        +set(key, value, roomKey)
        +unset(key, roomKey)
    }
    class WorldAdminCommandSuite {
        +register()
        +handleConfig()
    }
    class CasinoFeaturePlugin {
        +getRules()
        +handleEntry()
    }
    class ShopFeaturePlugin {
        +getRules()
        +handleLocation()
    }
    class LocationEntryBehaviorPlugin {
        +getConfig()
        +handleLocationEntry()
    }
    class MotdService {
        +select scheduled preset or MOTD_TEXT fallback
    }
    class CommunicationPlugin {
        +deliver selected greeting
    }
    class MongoDB {
        <<runtime-target database>>
        prototypeGameConfig
    }

    Startup --> MongoGameConfigRepository : seed casino.rules, shop.rules and location-entry-behavior.rules if missing
    MongoGameConfigRepository --> MongoDB : revision-CAS and transactional backups
    Startup --> GameConfigRuntime : load after seeding
    GameConfigRuntime --> MongoGameConfigRepository : watch and reload
    GameConfigRuntime --> CasinoFeaturePlugin : explicit room snapshot
    GameConfigRuntime --> ShopFeaturePlugin : explicit room snapshot
    GameConfigRuntime --> LocationEntryBehaviorPlugin : explicit room snapshot
    GameConfigRuntime --> MotdService : global motd.schedule snapshot
    PrototypeConfig --> MotdService : MOTD_TEXT fallback
    MotdService --> CommunicationPlugin : selected greeting
    WorldAdminCommandSuite --> GameConfigAdminService : room-admin commands
    GameConfigAdminService --> MongoGameConfigRepository : set/unset
    GameConfigAdminService --> GameConfigRuntime : apply successful local write
sequenceDiagram
    participant Main as Startup composition root
    participant Repo as MongoGameConfigRepository
    participant DB as prototypeGameConfig
    participant Runtime as GameConfigRuntime
    participant Admin as World config command

    Main->>Repo: setIfAbsent("casino.rules", baseline, "main")
    Repo->>DB: read singleton and check rooms.main key
    alt key is missing
        Repo->>DB: insert revision 1 if empty; otherwise CAS update and insert prior-revision backup transactionally
        DB-->>Repo: stored baseline and new revision
        Repo-->>Main: inserted = true
    else key already exists
        Repo-->>Main: inserted = false; preserve stored value
    end
    Main->>Repo: setIfAbsent("location-entry-behavior.rules", disabled baseline, "main")
    Repo->>DB: preserve existing key or write at next revision and back up prior revision
    Main->>Repo: setIfAbsent("shop.rules", default offers, "main")
    Repo->>DB: preserve existing key or write at next revision and back up prior revision
    Main->>Runtime: load persisted snapshot
    Runtime->>Repo: start change-stream watcher
    Admin->>Repo: set or unset room-scoped value
    Repo->>DB: transactionally update active config and insert prior-revision backup
    Repo-->>Runtime: successful write snapshot / change event
    Runtime-->>Admin: apply local write immediately

Prior revisions are stored as backup:<revision> documents in prototypeGameConfig. The update and backup insert commit or roll back together; MongoDB transaction support (a replica set) is required. Backups are not automatically pruned and are not included in the configuration-copy allowlist.

Bot Command Sequences

Use native /bot <command> or bang-prefixed !<command>. World and door configuration commands require current room-admin access and reply privately.

Casino rules

Inspect the seeded or existing settings:

/bot world config show room main

The same set command creates a missing room-scoped value or changes an existing one. This example changes the default rolling entry grant to 10 chips and keeps all game locations unbound:

/bot world config set room main casino.rules {"schemaVersion":1,"entryGrant":{"chips":10,"intervalMs":86400000},"locations":{"slots":[],"roulette":[]},"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

roulettePresentation is optional and its mode defaults to whisper. To opt in to the wheel helper, add the following object to the complete casino.rules value before validating and saving it:

{
    "roulettePresentation": {
        "mode": "wheel_helper",
        "agentId": "roulette-wheel",
        "openingTemplateId": "roulette-open",
        "spinningTemplateId": "roulette-spin"
    }
}

The referenced enabled helper and Emote templates live in the existing Helper Bots collections and must match the configured roulette-region key, room, and runtime. See the casino guide for the complete setup and fallback behavior.

To enable location-based help/access, first create and enable actual game locations, then set their database keys in locations.slots (point shape) or locations.roulette (region shape). Use the complete versioned rules object; the casino schema rejects unknown fields, unsupported shapes, global-scope rules, invalid schedules, and slot RTP above 99%. The guided location command creates point locations. Region geometry is operator-managed in veratownLocations; the current bot command does not create or edit region geometry. See the casino guide for full rules and location validation.

To remove the active room value:

/bot world config unset room main casino.rules
/bot world config show room main

Removal takes effect immediately and makes casino rules unavailable until the next startup, when the baseline is inserted again if the key is still absent. Unsetting does not remove the casino location documents or enable gameplay.

World locations, maps, and doors

Create a location through the guided prompts:

/bot world location create
/bot world answer <lowercase-key>
/bot world answer <display-name>
/bot world answer <location-type>
/bot world answer <X Y>          # or /bot world skip when no point is needed
/bot world skip                  # optional label
/bot world skip                  # optional description
/bot world answer yes            # enable it

For an edit, use /bot world location edit <key> and answer only fields to change; /bot world skip preserves the current value and none clears an optional text/position field. /bot world location list and /bot world location show <key> inspect the result. Map data is managed with /bot world map save, /bot world map edit, and revision/backup commands; a stored map is only a missing-room creation template, not a live-room mutation.

Create or update a door after verifying map coordinates and catalog tile style/type:

/bot door create <key> <doorX> <doorY> <lockedTile> <unlockedTile> [durationMs] [keypadX keypadY] [lockedTileType=Type] [unlockedTileType=Type]
/bot door update <key> <field> <value>
/bot door info <key>

The door commands also manage groups and memberships (/bot door group ..., /bot door access ...). Codes and membership are operator-supplied; defaults are not invented. See the map and doors guide for supported fields, validation, and full CRUD syntax.

Location behavior, appearance, communication, and status

` to apply a definition, not to create or edit it. The shared schema supports observed-body and BC-prerequisite conditional variants; feature-specific policies can still require a fixed set. The `APPEARANCE_QUALIFICATION_ENABLED=false` environment default remains separate. See the [appearance guide](/features/appearance/) for the exact itemset document. - **Communication:** manage message presets and weekday/time rules in the admin-web **MOTD** tab. The first matching rule in the configured IANA time zone wins; `MOTD_TEXT` remains the fallback for an absent, invalid, or unmatched schedule. `/bot testcomms ` is a diagnostic, not a configuration editor. - **Status:** `/bot prototype` reads status; the feature has no mutable game configuration. - **Dilemma:** the room config and prompt catalog are operator-managed directly in the isolated runtime database; startup seeds missing disabled rules and reviewed prompts, but there is no in-game editor. Keep `enabled` false until the room policy, prompt moderation, reward bounds, and consent flow are approved. Start with `/bot dilemma join`; a room admin starts the round with `/bot dilemma start`. See the [Dilemma guide](/features/dilemma/) for all commands and schema requirements. Feature configuration is distinct from player/runtime data. Do not add wallets, profiles, action history, or BC-observed room/character state to the startup-default mechanism.