This foundation provides source-driven BC asset discovery, validated room appearance observations, permission-aware planning, and journaled mutations. It does not own location-entry behavior or Release sessions.
The asset catalog is generated from Bondage-College at
51df6acc01f8fa185079d8deebf591fe3642a148 (R133), the same revision as the wire declarations.
It records source hashes and schema version: 85 groups and 2,662 assets.
BC now defines preset colors on individual layers; the extractor derives each
asset’s default color vector from those layer presets, including shared color
indices. The catalog preserves source data but does not execute rendering or
item callbacks.
Dynamic baseline and module-option getters are retained as unresolved metadata;
the generator never executes upstream code. BarStool’s dynamic decal options
remain visible in raw metadata but have no statically enumerated options, so
headless mutation is rejected. TentacleSuit’s d0/d1 option meanings changed
upstream; review operator-owned itemsets using these selectors and itemsets
pinned to older catalog revisions before use. The update does not rewrite stored
itemsets or widen lock support. The refreshed catalog adds four assets and
changes metadata on 87 existing assets. LegSpreadDisplayStand now carries
CanBackElbowTouch and CanKneelingSpread prerequisites, which the headless
pose evaluator supports. Its Gender: "F" metadata follows BC’s room-space
gender filtering; Veratown does not emulate that browser UI filter, so review
any itemset using it against the target room before activation. See the
2026-11-03 compatibility review,
the 2026-10-29 review, and
the previous source review.
Regenerate with:
BC_REPO=/path/to/Bondage-College npm run sync:bc-assets
Generation reads the pinned Git blobs, not the checkout’s potentially different HEAD. Asset/group definitions, extended configurations, display names, layer and color labels, and asset strings are data, not browser runtime imports. No socket endpoint provides the entire asset definition catalog. Definitions are refreshed by deliberate generation; character state and access are live BC observations.
Discovery is broader than mutation support. The codec has no item-name allowlist:
it interprets catalogued basic, typed, modular and noarch assets. Itemsets select
assets, colors, configurations, catalog-baseline configurable properties, craft
text and lock types in the database, not in feature code. The BC lock capability
catalog discovers all source-defined locks but enables only reviewed types;
requests use semantic options and duration bounds derived from each lock’s
MaxTimer. Mutation-critical properties cannot be injected through a set.
Every prerequisite used by an asset or selected option in the pinned catalog has
a headless evaluator. Unavailable evidence remains unknown and blocks mutation;
unrecognized prerequisites, unresolved definitions, dependent removals, exclusive
relationship permissions, and arbitrary property writes fail explicitly.
Resolved typed and modular choices, including shock levels and the Futuristic
Crate’s modules, use the same catalog-backed selectors in the appearance-set
builder. Assets whose configuration metadata contains unresolved callbacks are
not offered for itemset mutation; this includes some vibrating archetypes and
the Modular Chastity Belt in the current pinned catalog. The catalog’s numeric
Difficulty fields do not establish a validated range or item-level editing
semantics, so itemsets do not accept an independent difficulty override.
Appearance mutations can carry a JSON-safe craftSnapshot when a restoration
workflow needs to preserve the exact Craft metadata observed from BC. The shower
uses this only for catalogued, otherwise supported clothing; crafted metadata is
kept in bounded process memory and is not written to journals or persistence.
Itemsets and chat commands do not accept this snapshot field.
Appearance comparison canonicalizes omitted typed or modular TypeRecord
selections as BC’s default option (index zero). This handles equivalent minimized
and expanded server representations; non-default selections and unrelated
appearance properties remain part of the comparison.
The lock management proposal remains active for policy expansion; the implemented mutation contract is summarized below.
Required appearance/body groups cannot be removed; other body changes require
full wardrobe access. Clothing and cosplay classifications can overlap.
Owner/relationship and ambiguous locks are preserved. Removing another supported
lock requires explicit allowNonOwnerLock authorization and BC interaction access;
that flag is not a permission bypass.
Prerequisite evaluation mirrors the pinned Inventory.js semantics for body
traits, pose availability, effects, occupied groups, exposure/blocking clothing,
gag layering, equipment attributes, and the remaining catalogued inventory
rules. The target’s current item is removed from its group before evaluation, as
BC does. Body traits use observed BodyUpper and Pussy assets; pose and item
facts use the observed character plus pinned catalog properties. The evaluator
does not execute custom inventory scripts or browser callbacks.
NoErection means the character lacks the ForcedErection effect; arousal
progress is not a substitute. The pinned AccessFullPenis implementation checks
ItemArms against an empty list and therefore always passes; the headless
evaluator preserves that source-specific behavior. RemotesAllowed passes for
remote characters, but remains unknown for the bot’s own character because the
local BlockRemoteSelf owner setting is not part of the observed snapshot.
Unknown evidence is never treated as permission to apply an item.
BcLockCapabilityCatalog discovers all 18 lock assets declared by the pinned BC
source. Discovery does not authorize mutation: only these seven types have a
reviewed policy with no unresolved reasons. The admin itemset editor lists all
discovered lock types, but disables types that are unsupported or not approved
for shared itemsets, with the policy reason shown:
| Lock type | Supported semantic options | Credential path | Itemset support |
|---|---|---|---|
MetalPadlock |
None | None | Yes |
IntricatePadlock |
None | None | Yes |
ExclusivePadlock |
None | None | Yes |
TimerPadlock |
durationMs, removeItemOnExpiry |
None | Yes |
CombinationPadlock |
None | Required ephemeral combination | No |
PasswordPadlock |
hint, removeOnUnlock |
Required ephemeral password | No |
TimerPasswordPadlock |
durationMs, removeItemOnExpiry, showTimer |
Optional ephemeral/generated password | Yes |
The adapter maps semantic options to BC properties and validates them against
the selected type’s source metadata, including MaxTimer. Itemsets cannot hold
credentials; timer-password itemsets may use a generated ephemeral password.
The bot applies Intricate and Exclusive locks through the normal appearance
mutation path; their specialized key and unlock behavior remains BC-owned.
Live application qualification succeeded for both types; account-profile
persistence remains subject to separate qualification.
The appearance lock qualification command is a TimerPasswordPadlock convenience,
not a generic command for selecting any of the seven types.
Owner-, lover-, family-, high-security-, safeword-, and specialized browser-hook
locks other than IntricatePadlock and ExclusivePadlock remain unsupported.
Arbitrary BC Property fields are not accepted, and the existence of a source
asset never implies that its server-side authorization or inventory behavior is
supported.
classDiagram
class CharacterAppearanceApi {
<<core port>>
+execute(memberNumber, mutation)
}
class CharacterAppearanceLockApi {
<<core port; ephemeral credentials>>
+executeLock(memberNumber, request, secrets?)
}
class BcAppearanceAction {
<<shared BC implementation>>
+execute(memberNumber, mutation)
+executeLock(memberNumber, request, secrets?)
}
class BcLockCapabilityCatalog {
+list()
+get(type)
}
class BcAppearanceCodec {
+plan()
+matches()
}
class ActionCoordinator
class BcClient
CharacterAppearanceApi <|.. BcAppearanceAction
CharacterAppearanceLockApi <|.. BcAppearanceAction
BcAppearanceAction --> BcLockCapabilityCatalog
BcAppearanceAction --> BcAppearanceCodec
BcAppearanceAction --> ActionCoordinator
BcAppearanceAction --> BcClient
sequenceDiagram
participant Feature
participant API as CharacterAppearanceLockApi
participant Action as BcAppearanceAction
participant Catalog as BcLockCapabilityCatalog
participant Codec as BcAppearanceCodec
participant Journal as ActionCoordinator
participant BC as BcClient / BC
Feature->>API: executeLock(request, ephemeral secrets)
API->>Action: validated request
Action->>BC: check interaction permission and read current appearance
Action->>Catalog: resolve reviewed type policy
Catalog-->>Action: supported options or rejection
Action->>Codec: plan against observed item and lock state
Codec-->>Action: mutation plan or rejection
Action->>Journal: record requested lifecycle
Action->>BC: guarded appearance update
BC-->>Action: later matching observation, if received
Action->>Journal: observed / timed_out_unobserved / failed
Action-->>Feature: ActionOutcome
The read-only runtime repository uses prototypeItemSets in the database
selected by the fixed runtime target (veratown_prototype for production or
veratown_prototype_test for testing). Runtime startup never writes this
collection. The dry-run-first party-game provisioner seeds six validated,
strip-only Staged Table stage itemsets if absent; all other itemsets, including
emergency.release.clothing, remain operator-authored. An operator can create
or edit definitions in that collection:
{
"_id": "appearance.restraints",
"schemaVersion": 1,
"revision": 1,
"enabled": true,
"pieces": [
{
"group": "ItemArms",
"asset": "HempRope",
"configuration": { "kind": "typed", "option": "BoxTie" },
"color": "#FF69B4",
"lock": { "type": "TimerPasswordPadlock", "durationMs": 300000 }
}
]
}
This is an example shared appearance itemset. Replacing the asset or
selection requires changing only the document and incrementing its revision.
The same service and codec load the new definition on the next application,
without code changes or a restart. New upstream asset definitions still require
deliberately regenerating the pinned catalog.
Definitions are versioned and validated: at most 128 pieces, one per group,
nonempty group identifiers, JSON-safe properties, and timer durations no greater
than the selected lock’s source-defined maximum. An itemset may also specify
unique stripGroups from the pinned catalog. Before applying pieces, it removes
the target’s currently observed item from each selected, removable group using
the same permission, lock, dependency, observation, and journal checks as an
explicit removal. Selected removals are ordered around catalog-declared
dependencies; a dependency cycle is rejected before any mutation. A set can be
strip-only, and selected groups with no current item need no removal mutation.
Observed mod items missing from the pinned catalog remain in the strip sequence
and are reported as skipped; other set operations continue.
An itemset may carry up to 16 optional variants, each with a when condition
group, optional stripGroups, and pieces. Conditions compare a supported fact
to true or false with equals. Body facts hasBreasts, hasFlatChest,
hasVagina and hasPenis come only from the target’s observed BC appearance
(BodyUpper Small/Normal/Large/XLarge → breasts, FlatSmall/FlatMedium → flat
chest; Pussy Pussy1-3 → vagina, Penis → penis). Missing or unrecognized body
assets leave those facts unknown.
prerequisitesSatisfied:<Group>:<Asset> evaluates the selected BC asset’s
catalogued prerequisites against the target’s latest observed character state.
If that asset is included in the candidate variant, its selected configuration
and option prerequisites are checked too. If required evidence or an extended
configuration is unavailable, the condition is unknown and does not match.
Evaluation follows BC’s replacement semantics: the current item in the candidate
asset’s group is excluded before its prerequisites are checked. Only an observed
character snapshot can select a variant; unavailable evidence never counts as
satisfied.
The Admin Web editor uses the same pinned catalog for the group and asset
selectors; it does not connect to BC or preview live eligibility.
At apply time the first matching variant is merged over the base set: strip groups are unioned and the variant’s pieces replace base pieces in the same group. With no match the base set applies; a set with an empty base and no matching variant fails with no mutation. Every variant is validated with the same catalog, lock, and policy rules as the base. Features with stricter itemset policies (Trick-or-Treat costumes, favors, emergency release, and Staged Table appearance) reject sets that contain variants.
The admin set builder can filter the item picker to items BC restricts to
breasts/vagina (“women’s”) or flat chest/penis (“men’s”) through the
Body requirement filter, and edits these conditions in the Conditional
variants section. The first matching variant applies; if none match, the base
set applies, or an empty-base itemset fails without mutation.
Stripping does not bypass required-group safeguards or infer appearance from
database state. The optional allowNonOwnerLockRemoval itemset flag requests
removal of supported non-owner locks during stripping. It does not remove owner
or relationship locks, resolve ambiguous lock metadata, or bypass BC permissions.
The flag is shown in the admin itemset editor and defaults to off. Itemsets may specify
removeItemOnExpiry and showTimer only where that lock’s reviewed capability
allows it. An optional catalogRevision pins a definition to one catalog.
BC’s empty-name body assets are valid asset identities, not item removals.
Typed selection uses the option’s catalog name; modular selection supplies every
module key and its zero-based option index. A noarch selection needs no options.
properties can override fields declared by the extended baseline with matching
types; unspecified fields inherit their catalog defaults. Effects, poses,
permission selectors and lock internals are protected.
The separate configuration dashboard provides an authenticated, audited editor for creating and updating shared itemsets. Its selectors use a compact projection of the pinned BC catalog and omit assets with unresolved or unsupported configuration metadata. Search across the full catalog by group, category, asset name, or description, then select a blueprint and configure its supported options. The editor shows catalog-declared instance-property defaults and persists only customized overrides on each set item. It also supports typed and modular selections, color layers, reviewed itemset-compatible locks, and selecting groups to strip before applying pieces. Unsupported lock types remain visible but cannot be selected; credentials and unreviewed lock behavior are not accepted. From a location in the map workspace, operators can open or create its referenced appearance set directly in this editor. Strip-only sets are supported. It does not connect to BC or apply appearance changes. Set keys remain stable for location-entry behavior and shop references, and the dashboard does not expose deletion.
Each application snapshots one document revision and holds the per-character
queue for the whole set. Strip removals run before apply pieces; catalog-declared
dependencies order selected removals, while apply pieces follow document order.
A denied, occupied or unsupported operation is reported as skipped; an emitted
but unobserved write is unconfirmed. The result is completed, partial or
failed across both strip and apply operations. No skipped operation is silently
treated as success. Each mutation has its own journaled action and records the
set key, revision and sequence index; there is no second journal owner wrapping
those mutations. Shop favor sets remain apply-only.
Worn mod items absent from the pinned catalog are preserved and ignored when
checking catalog-defined blocking, enclosure and prerequisite metadata.
Set edits do not replace already occupied slots, retroactively alter active punishments or schedule releases. Clean up the previous feature session before applying a changed set. Automated session ownership and recovery remain later phases.
stateDiagram-v2
[*] --> Queued
Queued --> PermissionQuery
PermissionQuery --> Failed: denied / unknown / cancelled
PermissionQuery --> Plan: allowed
Plan --> Failed: unsupported / occupied / protected
Plan --> AlreadySatisfied: current BC observation matches
Plan --> JournalRequested
JournalRequested --> Failed: journal unavailable
JournalRequested --> Dispatch: current revision still matches
Dispatch --> Failed: cancelled / stale revision
Dispatch --> AwaitObservation
AwaitObservation --> Observed: later matching full appearance
AwaitObservation --> TimedOutUnobserved: no matching evidence
AwaitObservation --> Failed: disconnect / leave / stop
One per-character queue serializes mutations across callers. All packets use the existing BcClient rate limiter. Full updates preserve the character ID, active pose, and unrelated appearance items. The input revision and cancellation signal are checked again immediately before the rate-limited queue emits the packet. There is no optimistic snapshot patch, strip-and-restore, or automatic retry. After an unconfirmed emitted write, later bundle writes are refused until a fresh authoritative BC appearance observation arrives. This prevents subsequent pieces from overwriting an earlier, possibly successful write using a stale snapshot. An emitted permission query that times out or is cancelled quarantines that member’s permission channel until reconnect, preventing a late response from being mistaken for the result of a retry.
BC observations come from full room/character syncs, single-item patches, pose
updates, and expression updates. Connection epochs invalidate stale snapshots.
Malformed appearance events are reported without logging their payloads.
Omitted optional sync fields use the pinned browser’s documented defaults:
empty active pose and permission lists, full wardrobe access off, and body
cosplay blocking off. Malformed supplied fields are not treated as defaults.
Omitted AssetFamily uses Female3DCG, matching the pinned browser’s
CharacterCreatePlayer and CharacterLoadOnline initialization. Supplied malformed
or unsupported families are rejected rather than replaced with that default.
The pinned BC browser source explicitly states that single-item updates are not
echoed to the sender. Phase 1 therefore uses the full-character update path and
requires a later, matching appearance observation. This is sufficient convergence
evidence for bot operation: local inbound BC room updates do not need independent
helper corroboration, a particular source member, or a second confirmation.
Features such as shower consume the action result directly. Evidence retains
temporal_match_only attribution, not causal acknowledgement or proof of
account persistence. No inbound signal means timed_out_unobserved, not success.
Generic action journal metadata contains asset identifiers and catalog revision, plus non-secret lock intent; it never contains appearance bundles, colors, craft text, or credentials. Explicit password/combination locks take credentials on a separate ephemeral API path; they are never accepted from itemsets or chat. TimerPasswordPadlock itemsets use an internally generated ephemeral password. The feature-specific durable session/projection repositories belong to later phases.
Qualification is disabled by default:
APPEARANCE_QUALIFICATION_ENABLED=false
Enable it explicitly only with the dedicated prototype account in a test room.
Commands work through native /bot appearance ... and !appearance ....
The sender must be a room administrator. Mutations can target only the sender’s
own character, so administrators cannot use this qualification surface to
modify another player.
/bot appearance inspect <memberId>
/bot appearance applyset <memberId> <itemsetKey>
/bot appearance apply <memberId> Cloth <simpleAsset>
/bot appearance apply <memberId> ItemArms HeavyYoke
/bot appearance apply <memberId> ItemFeet HeavySpreaderMetal typed Wide
/bot appearance apply <memberId> ItemDevices FuturisticCrate modular w=2,l=3,a=3,d=1,t=1,h=4
/bot appearance configure <memberId> ItemFeet HeavySpreaderMetal typed Narrow
/bot appearance lock <memberId> ItemArms HeavyYoke 5
/bot appearance remove <memberId> ItemArms HeavyYoke non-owner
There are no asset-specific command shortcuts. The direct lock command is a
TimerPasswordPadlock qualification convenience (1-240 minutes); database itemsets
select supported lock types and catalog-approved options generically. Occupied
slots are not implicitly replaced. Keep manual BC/admin cleanup available:
Phase 1 does not schedule feature release workers.
Before enabling automated features, live qualification must demonstrate:
Fake-socket tests cover the contracts but cannot establish real-server delivery, browser acceptance, or durable account persistence.
The opt-in harness uses TESTVERATOWN2 as the driver and subject, and the primary account as the system under test. It sends native self-targeted commands through the existing admin gates; each account has its own client and connection. It does not modify operator characters, grant room-admin access, seed itemsets, or enable separate Cage or Release automation. Location Entry Behavior has its own room-scoped opt-in configuration.
Implementation or offline testing does not authorize a live run. Obtain explicit approval before connecting the accounts or stopping the normal primary. Do not leave a browser logged into either bot account during testing.
.env.appearance-qualification.example to the git-ignored
.env.appearance-qualification.local and supply the dedicated test password
locally. Never commit credentials. The existing .env supplies primary
credentials and the room; qualification must already be enabled.Cloth slot must be empty; existing clothing is never replaced.Run with Node 24:
npm run qualify:appearance:faults -- --confirm-live --confirm-primary-stopped --primary-member 261407
The harness tests withheld observations and the unconfirmed-write guard, cancellation
before and after emission, queued work after stop, actual socket disconnect, actual
target departure, and SIGTERM shutdown. Observation withholding is local fault
injection, not evidence that BC naturally failed to echo. One unlocked
Cloth/BusinessSuit is used; there are no restraint or lock tests in this runner.
Fault windows are bounded. After each scenario, the primary is restarted to obtain
fresh room observations before cleanup; stale snapshots are never replayed.
Success requires exact update counts, terminal outcomes, observer cleanup,
independent target-side room observations, appearance preservation, and terminal
journal read-back in veratown_prototype.prototypeActions. The JSON summary is
printed only after verification. A failed run exits nonzero and warns when clothing
may remain; inspect the dedicated account before any retry. The harness closes its
connections when finished. Restart the normal primary afterward, including after
failure. It does not prove durable BC account persistence or browser rendering.
Offline validation:
npm run test:appearance-faults
qualify:appearance:browser-correction runs TESTVERATOWN2 in a fresh, headless
Chromium browser using the actual BC web application. It does not also start
the headless Socket.IO driver for that account. The primary still runs the normal
prototype composition with explicit, test-only socket interception.
Install the development dependencies and browser binary before offline validation:
npm install
npx playwright install chromium
npm run test:appearance-faults
The same dedicated-account prerequisites and separate live approval apply. Stop the normal primary and log out the dedicated account elsewhere before executing:
npm run qualify:appearance:browser-correction -- --confirm-live --confirm-primary-stopped --primary-member 261407
By default the browser opens ${BC_ORIGIN}/R133/BondageClub/, matching the
selected source’s GameVersion. A successful run requires the browser to report
that version. If the configured BC
host uses a different game path, set BC_TEST_BROWSER_URL in the ignored local
qualification environment file. The URL must remain HTTPS on the configured BC
origin; the browser’s actual server endpoint must match BC_SERVER_URL before
credentials are sent. Credentials are not traced, screenshotted or printed.
Appearance qualification runners derive this URL and exact version check from the shared source pin. Custom same-origin paths cannot bypass that check. The Bunny manual observation sequence records the actual displayed version; R132 and R133Beta2 observations do not qualify R133. This repin includes offline verification only and does not renew any live approval.
The test uses one unlocked Cloth/BusinessSuit and requires that slot initially
empty. After the real browser receives the requested clothing, automation invokes
BC’s native InventoryRemove, refreshes the real character canvas without requesting
an account save, and calls native ChatRoomCharacterUpdate. This is a native browser
wardrobe edit, not a claim that a simulated mouse click or an automatic asset-validation
repair was tested.
To keep the action pending deterministically, the primary locally withholds the initial matching echo. It forwards, rather than fabricates, the actual corrected full appearance received from BC, bound to the dedicated character and its native source member. Passing requires:
timed_out_unobserved, with exactly one primary appearance write and no retry.The report includes the actual browser game version, pinned catalog revision, operation ID, corrective event and sequence. Offline tests exercise Chromium against a local fixture and cannot substitute for live BC qualification. Restore the normal primary after the run. Durable BC account persistence remains outside this qualification.
The approved automated run completed successfully in Veratown2, using
TESTVERATOWN2 (261575) as the dedicated subject and TestVeraTown (261407) as the
primary. Only the dedicated subject’s unlocked Cloth/BusinessSuit was changed.
| Check | Result | Appearance updates |
|---|---|---|
| Withheld-observation timeout | Passed | 1 |
| Unconfirmed-write guard | Passed | 0 additional |
| Cancellation before write | Passed | 0 |
| Cancellation after write | Passed | 1 |
| Queued work after stop | Passed | 0 additional |
| Actual socket disconnect | Passed | 1 |
| Actual target departure | Passed | 1 |
| SIGTERM shutdown | Passed | 1 |
Timeout, cancellation, disconnect and departure produced the expected unsuccessful
action outcomes, not false success. The runner verified observer cleanup, independent
target-side observations, cleanup after fresh primary connections, restoration of
the subject’s initial appearance, and terminal status read-back for all 13 action
records in veratown_prototype.prototypeActions. The run exited with code 0.
Both harness connections closed, and the normal primary was restarted and observed
ready in Veratown2. Existing operator itemsets were not changed.
Previously guided live tests also demonstrated basic, clothing, cosmetic cosplay, typed and modular round trips; active timer-lock removal; occupied-slot refusal; protected owner-lock preservation; and a database-only HeavyYoke-to-HempRope revision change without restarting the bot, with explicit partial outcomes and idempotency. All added test items were removed; the dedicated itemset document was deleted and the operator’s temporary native cosplay permission change was restored.
The separately approved real-browser run also passed against the official R132 BC
application, using the same dedicated subject and primary. The actual target-origin
ChatRoomSyncSingle correction advanced the primary’s normal appearance reducer to
sequence 4 while the action was pending. It restored the initial appearance but did
not falsely confirm the requested clothing. Operation
9b57e121-a172-493a-8e0c-39676b8bc57d ended timed_out_unobserved, with emitted-write
evidence, exactly one primary appearance write and no retry. Browser baseline,
observer cleanup and terminal MongoDB journal status were verified; the runner exited
with code 0 and closed its connections. The normal primary was rebuilt, restarted and
observed ready in Veratown2 after this run.
Observation withholding was local injection in both automated scenarios. The browser test performed a native wardrobe edit and canvas refresh; it did not simulate a mouse click or prove spontaneous asset-validator repair, visual rendering quality or durable BC account persistence.