veratown-prototype

Runtime Environment Isolation

Local testing and Railway production use the same Bondage Club server but run in different rooms and write to different MongoDB databases.

Setting Local test Railway production
RUNTIME_TARGET test production
BC_ROOM Veratown2 Veratown
MONGODB_DATABASE veratown_prototype_test veratown_prototype

The database names are fixed for each target. The application rejects a database that does not match RUNTIME_TARGET; do not use the legacy ropeybot database as a runtime database. A shared MongoDB cluster and URI are supported, but all runtime writes remain in the selected database.

abcl.rules is stored in the selected runtime database’s existing prototypeGameConfig room scope. The configuration-copy script does not copy prototypeGameConfig, ABCL consent, transient ABCL decisions, helper tasks, or action journals. Configure and qualify the test instance separately before production; never copy participant consent between environments.

Runtime roles

The statically composed process role is selected from the database profile when BOT_INSTANCE_ID is set; otherwise RUNTIME_ROLE (or the legacy helper fallback) selects it:

Role Composition
supervisor Default Veratown runtime and feature set.
helper One helper worker; HELPER_AGENT_ID comes from the profile or environment. Omitting RUNTIME_ROLE with a legacy environment HELPER_AGENT_ID still selects helper mode.

The supervisor runs ABCL coordination when abcl.rules is enabled; a separate helper with the abcl capability observes mod messages and performs assigned work. Missing, disabled, or invalid ABCL configuration leaves that feature inactive without blocking the supervisor. The old abcl runtime role is rejected. Existing profiles with that role remain available for administrative migration; change them to supervisor or disable/retire them.

Each role uses the same fixed RUNTIME_TARGET database mapping and a separate dedicated BC account per service. BOT_INSTANCE_ID is the stable deployment identity used to load a typed, versioned profile from that target database after Mongo connects. The profile’s role overrides RUNTIME_ROLE and selects the existing static composition; it can also supply the BC server/origin/room, helper identity, and supported non-secret capabilities. Keep RUNTIME_TARGET, MONGODB_URI, BC username/password, and observation bearer tokens in deployment settings/secrets. A profile stores the matching runtime target only as scope metadata; it cannot select a database or override the bootstrap target. Without an instance ID, the existing environment-only configuration continues to work.

Profile writes are desired configuration, not remote container control. Changes take effect on the next process start; stop a running service manually when disabling it. Runtime reports show the loaded revision and role alongside the latest desired revision, role, enabled state, and whether a restart is required. The helper is an independent process and must be freshly observed in the configured ABCL region before it can perform ABCL work. See the ABCL feature guide and its Railway how-to.

Local test setup

The current source pin is Bondage-College 51df6acc01f8fa185079d8deebf591fe3642a148 (R133). Previously reported R133Beta2 checks are historical and do not qualify this version or authorize deployment; qualify the configured BC server and release target separately.

The 2026-11-03 source sync adds tether protocol/map metadata and refreshes the appearance catalog. The 2026-10-29 source sync refreshes item color defaults and catalogs and adds map-object migration metadata. The 2026-10-22 source sync records the still applicable teleporter cell configuration. Qualify map round-trips and review operator-owned itemsets with changed selectors or older catalog revisions before activation. Older sign-only readers reject teleporter-bearing maps; do not roll back while continuing map administration or room recreation against those documents.

For the R133Beta2/map-sign change, offline implementation does not authorize a database inspection, migration, live connection, or deployment. Before rollout, obtain separate read-only approval to audit existing sign counts/UTF-16 lengths without reporting text. Stop for values above the 150-code-unit bot policy; there is no automatic truncation or backfill. Qualify actual-version rendering, save/restore, missing-room creation, door updates, and reconnect separately. Before rolling back to older code, suspend map save/edit/backup/recreation and retain sign-bearing documents unchanged. See the map contract.

The operator subsequently reported passing the Beta2/map-sign manual checks and existing-sign audit on 2026-10-15. The supplied context was “Personal Commit”, without an exact build or room/environment; the assistant did not observe the run. See the archived qualification record. Confirm applicability to the release target separately. No deployment approval or unrelated feature qualification is implied.

  1. Configure .env with a dedicated test bot account, the test room Veratown2, RUNTIME_TARGET=test, and a MongoDB URI that can access veratown_prototype_test.
  2. Set MONGODB_DATABASE=veratown_prototype_test. If omitted, the application selects the fixed database for the target automatically.
  3. To initialize the test database with room/map/location/door configuration, set the approved source database and run the dry run:

     SOURCE_MONGODB_DATABASE=veratown_prototype npm run copy:veratown-config
    

    This is a dry run and lists document counts only. Review it, then explicitly apply the allowlisted configuration copy:

     SOURCE_MONGODB_DATABASE=veratown_prototype npm run copy:veratown-config -- --apply
    

    The default copy upserts source documents and leaves destination-only documents unchanged. To recreate only the allowlisted test configuration collections from current production configuration, stop test bot/admin writers and first review a replacement dry run:

     SOURCE_MONGODB_DATABASE=veratown_prototype npm run copy:veratown-config -- --replace
    

    After reviewing the source and destination counts, apply the replacement:

     SOURCE_MONGODB_DATABASE=veratown_prototype npm run copy:veratown-config -- --replace --apply
    

    --replace is restricted to veratown_prototype → veratown_prototype_test. It atomically deletes and recreates documents only in the seven allowlisted room, map, backup, location, keypad-door, keypad-group, and membership collections; it preserves their indexes and all other test database collections. A source collection with zero documents clears that allowlisted destination collection. It does not copy player profiles, sessions, or audit history. Both copy modes validate all source documents, use bounded cursors, and write in batches. Room templates are applied to the configured BC_ROOM name when the bot joins or creates the room.

  4. Inspect normalization drift in the selected isolated database without changing it:

     npm run migrate:mongodb-contracts
    

    The dry run checks the full legacy itemset and map document contracts, and reports missing itemset versions, main-room scope/casing normalization, and missing heartbeat TTL dates. It preserves String/ObjectId identities, grant metadata, and null group-key semantics. Only after reviewing the report and obtaining approval for that exact target, apply with:

     npm run migrate:mongodb-contracts -- --apply
    

    The tool requires RUNTIME_TARGET and enforces its fixed database pairing; it does not copy from or write to the source database, deletes nothing, and does not alter legacy prototypeBunnyStates documents. Location Entry Behavior does not read or write that legacy collection. Heartbeat dates are based on the stored lastSeenAt plus 30 days. Runtime startup idempotently creates only additive non-unique map query indexes and the prototypeRuntime.expiresAt TTL index before using those repositories. MongoDB TTL cleanup is asynchronous; expiry dates are not a guarantee of immediate deletion.

  5. Inspect the casino-to-economy migration for the fixed test database:

     npm run migrate:casino-economy
    

    The command is read-only by default and reports wallet/ledger counts and aggregate available/reserved credits. Review the output and stop any runtime using the test database before applying:

     npm run migrate:casino-economy -- --apply
    

    The migration uses only veratown_prototype_test, leaves the legacy collections in place, and writes a durable marker required by runtime startup. It never reads the source database. Production requires a separate reviewed dry run and explicit approval before applying to veratown_prototype.

  6. Start locally with npm start.

Railway production setup

Party-game provisioning and activation

The five prompt-based party games seed missing, disabled main-room configs and ten non-explicit English prompts each at startup. Trick-or-Treat seeds a disabled config without checkpoints; configure its route separately in Admin Web. Existing settings, enabled state, prompt content, revisions, and moderation decisions are preserved. Truth/Dare’s starter catalog has five truths and five chat-only dares; Hot Seat has ten truth/bluff preference prompts; Staged Table has ten fictional chat prompts; Dilemma has ten fictional A/B scenarios; Anonymous Whisperer retains its ten consent-aware conversation prompts.

Before activation, review the feature-owned catalogs and confirm an adults-only, opt-in policy for the selected room. The 2026-10-15 activation approval and Truth/Dare qualification results were reported by the operator (bidding, settlement, decline, timeout, and restart recovery succeeded), not independently observed by this tool. Truth/Dare’s code gate is now open, but room config and per-round player consent remain required. Staged Table appearance is available only through its separately validated, revision-pinned stage and emergency-release itemsets and a fresh participant opt-in. Provisioning seeds six strip-only stage defaults if absent, but does not configure an appearance plan or enable appearance mode.

Use the local protected MongoDB URI; never print it or put it in a shell command. Run each approved target separately:

RUNTIME_TARGET=test MONGODB_DATABASE=veratown_prototype_test npm run provision:party-games -- --enable --confirm-adults-only
RUNTIME_TARGET=production MONGODB_DATABASE=veratown_prototype npm run provision:party-games -- --enable --confirm-adults-only

These are read-only dry runs, including on an empty database. The plan lists each collection/document ID and exact operation. It validates existing records, requires at least ten usable prompts per game, validates the six Staged Table stage itemsets against the pinned BC catalog, and refuses unsupported locales, insufficient reviewed catalogs, or invalid schemas before making any writes. Without --enable, it only inserts missing disabled defaults, prompts, and Staged Table stage itemsets.

After reviewing each plan and approving its target, repeat that exact command with --apply. Activation requires --confirm-adults-only; this is an operator room-policy attestation, not age verification. Inserts use $setOnInsert, and existing configs change only enablement/policy confirmation, revision, and updatedAt. Stale revisions fail explicitly instead of overwriting admin edits. Catalog writes precede enablement. If a write fails, earlier writes may remain; rerun the dry run to inspect the remaining work before applying again.

Successful application reads back the configurations and eligible prompt counts. It fails if the resulting plan is not empty. Re-running is idempotent. The script touches only prototypePartyGameConfigs, the five prompt collections, and the six allowlisted Staged Table stage itemsets in the fixed selected database: no source reads, account creation, credit grants, economy migration, or session mutation.

Deploy the updated runtime for startup defaults and the approved Truth/Dare code gate, then restart any running runtime to reload Whisperer’s startup-only config. Database readiness does not prove BC delivery or a completed live round.

Party-game index compatibility

Anonymous Whisperer, Truth/Dare, Hot Seat, Staged Table, and Dilemma share the unique { roomKey: 1, gameId: 1 } index on prototypePartyGameConfigs. Startup uses party_game_config_room_game for new databases and reuses an existing whisperer_room_game_config index by requesting the same keys and unique option under its legacy name. Incompatible options and unrelated MongoDB errors still fail startup; no index is dropped or renamed and no configuration is overwritten.

For a startup crash reporting IndexOptionsConflict (code 85) with either of these names, deploy the compatibility fix and restart. No manual index deletion or data migration is required for an otherwise matching unique index.

Production variables and migrations

Set these values on the production bot service:

RUNTIME_TARGET=production
BC_ROOM=Veratown
MONGODB_DATABASE=veratown_prototype

Keep the production bot credentials and MongoDB settings in Railway variables, not in the local .env. Do not set the production service to the test target.

Do not run the configuration-copy or contract-normalization scripts against production until their dry-run output has been reviewed and a separate production change has been approved. Applying the contract normalizer is an operator action; connecting or deploying the updated runtime is separate and also initializes the safe runtime indexes.

Before deploying the shared economy, inspect and apply its migration separately:

npm run migrate:casino-economy
npm run migrate:casino-economy -- --apply

Stop the runtime during migration. Startup fails closed until the economy cutover marker exists. The migration touches only the selected runtime database, retains the legacy casino collections, and preserves 60-day settled-ledger retention. It never reads or writes ropeybot.

For a rollback during the 60-day approved window, stop the runtime first and review the inverse operation:

npm run migrate:casino-economy -- --rollback
npm run migrate:casino-economy -- --rollback --apply

Rollback copies shared account balances and entry-grant timestamps to the legacy casino wallets. It is refused after non-entry-grant economy activity because that activity cannot be represented by the legacy casino wallet. Casino slots and roulette were approved for activation on 2026-10-15. Once wagering creates non-entry-grant activity, this legacy rollback is unavailable; stopping gameplay does not restore eligibility. A rollback-compatible deployment must keep casino wagering and new game plug-ins disabled.