Status: Partially implemented. The shared appearance adapter discovers all 18 pinned BC lock assets and permits mutations for seven reviewed types. This document remains active because the other lock policies and live qualification are not complete; see the appearance guide for the implemented contract.
Provide one reusable, validated way for workflows to apply a BC lock to a character appearance item. The feature-neutral mutation contract is:
await appearance.execute(memberNumber, {
operation: "lock",
item: { group: "ItemArms", name: "HeavyYoke" },
lock: {
type: "TimerPadlock",
options: { durationMs: 5 * 60_000, removeItemOnExpiry: false },
},
});
The caller selects the target, item, lock, and supported options. The shared BC
adapter resolves lock capabilities, validates current item and lock state,
creates the canonical appearance mutation, dispatches it once, and reports the
strongest BC observation available. Credential-bearing locks use the separate
CharacterAppearanceLockApi.executeLock path so secrets never enter mutation
documents or itemsets.
Scope assumption: “item” means an item in a character’s appearance, not a room map object, door, inventory stock count, or account-level setting. This proposal does not add a general-purpose lock command or enable automated gameplay behavior; the appearance qualification command remains test-only.
At the pinned BC revision, the lock is an ItemMisc asset attached to an
appearance item. The target item’s properties carry LockedBy and lock-specific
fields; the lock itself is not a separate room object and there is no generic
wire-level “lock item” request. InventoryLock checks that the selected asset
is a lock and that the item’s current asset/configuration allows locks, then
adds the lock metadata. The server validates the submitted appearance update.
The valid target is therefore an existing appearance item whose asset has
AllowLock enabled. A typed or modular item can further restrict lockability
to particular selected options through AllowLockType. PortalLinkPadlock has
an additional PortalLinkLockable attribute requirement and is disabled in the
general asset definition at this revision. The actual browser UI may also
require inventory availability and interaction/relationship permissions; a
catalog entry alone does not prove that a bot can apply the lock or consume an
inventory item.
The complete AssetLockType union contains 18 names. Timer values below are
the asset-definition MaxTimer values, not unconditional guarantees: BC
normalizes an expiry that exceeds the lock asset’s maximum and consults the
target’s online LockTimerLimit for that normalization. BC’s observed state is
authoritative.
| BC lock type | BC capability and relevant options | Where / when it applies |
|---|---|---|
MetalPadlock |
Standard keyed lock; the matching inventory key is MetalPadlockKey. |
Any currently lockable appearance item; no lock-specific timer or relationship flag in the definition. |
IntricatePadlock |
Pick difficulty 7; has ExclusiveUnlock behavior and records the applying member. |
Any lockable item, subject to the browser’s exclusive-unlock/key behavior. It has specialized browser hooks; do not model it as a plain key lock. |
HighSecurityPadlock |
Pick difficulty 10; ExclusiveUnlock; MemberNumberListKeys stores eligible keyholder member numbers. |
Any lockable item. Keyholder-list editing and permission semantics need explicit support; the list is not a generic allow-list for other lock types. |
TimerPadlock |
Timer lock; definition has MaxTimer 300 seconds and RemoveTimer default 300 seconds. Supports RemoveItem on expiry. |
Any lockable item. BC’s effective timer limit may differ from the nominal five-minute maximum. |
CombinationPadlock |
Four-digit CombinationNumber (0000 is the baseline); BC permits lock inspection while blind. |
Any lockable item. Combination configuration is sensitive and must use BC’s format. |
PasswordPadlock |
Password is 1–8 uppercase letters; Hint, LockSet, and RemoveOnUnlock are lock-specific properties. |
Any lockable item. Requires a deliberate credential setup; the baseline value is not a user-selected secret. |
TimerPasswordPadlock |
Password-style lock with timer; nominal MaxTimer 14,400 seconds. Also supports RemoveItem, ShowTimer, EnableRandomInput, and MemberNumberList. |
Any lockable item. Credential and timer settings must both be validated; timer controls are not all equivalent to arbitrary expiry writes. |
OwnerPadlock |
OwnerOnly; matching OwnerPadlockKey; ownership and self-lock rules apply. |
Only where the target/actor relationship satisfies BC owner-lock validation. |
OwnerTimerPadlock |
OwnerOnly; nominal MaxTimer 3,024,000 seconds (35 days); timer controls include RemoveItem, ShowTimer, EnableRandomInput, and MemberNumberList. |
Owner-lock rules apply, plus BC timer-limit handling. |
LoversPadlock |
LoverOnly; matching LoversPadlockKey; lover relationship rules apply. |
Only where BC recognizes the required lover relationship. |
LoversTimerPadlock |
LoverOnly; nominal MaxTimer 604,800 seconds (7 days); timer controls as for the other relationship timer locks. |
Lover relationship and timer-limit rules both apply. |
FamilyPadlock |
FamilyOnly; matching FamilyPadlockKey; family relationship rules apply. |
Only where BC recognizes the required family relationship. |
MistressPadlock |
Matching MistressPadlockKey; no OwnerOnly, LoverOnly, FamilyOnly, or timer flag in the asset definition. |
A distinct BC lock/key path. Do not infer relationship permissions from its name. |
MistressTimerPadlock |
Matching MistressPadlockKey; nominal MaxTimer 14,400 seconds (4 hours), with timer controls. No relationship-only flag in the asset definition. |
Distinct BC lock/key path plus timer-limit handling. |
PandoraPadlock |
Matching PandoraPadlockKey; extended configuration is copied from MistressPadlock. No timer or relationship-only flag in the definition. |
Specialized BC/game inventory path; not a generic alias for MistressPadlock. |
ExclusivePadlock |
Specialized browser unlock rule: BC’s DialogCanUnlock does not allow the wearer to unlock their own item through the usual check. |
Any otherwise lockable item only when BC’s special interaction semantics are intended and qualified. |
SafewordPadlock |
Uses the password-lock configuration/UI hooks with a distinct safeword lock path. Password-shaped properties include Password, Hint, and LockSet. |
Any lockable item, but safeword semantics must remain BC-owned; do not treat it as an ordinary password lock. |
PortalLinkPadlock |
Disabled in the general asset definition; InventoryLock and server validation require PortalLinkLockable. |
Portal Link system only. Exclude from general-purpose appearance lock selection. |
Timer locks in this list have a definition-level RemoveTimer default of 300
seconds. That default is not the same as a caller-selected duration. The
relevant lock assets also declare RemoveItem behavior, and some timer-lock
types have additional timer display/input controls. The proposal should expose
only options validated for the selected type, not arbitrary BC property names.
The pinned BC property declarations identify these lock-specific values:
| Option family | BC properties | Types / caveats |
|---|---|---|
| Timer | RemoveTimer, RemoveItem, ShowTimer, EnableRandomInput, MemberNumberList |
RemoveItem is used by the timer locks. Display/input/member-list controls are only documented for selected timer-lock types. The server may normalize the requested timer. |
| Password | Password, Hint, LockSet, RemoveOnUnlock |
Password is 1–8 uppercase letters. RemoveOnUnlock is for PasswordPadlock; password and safeword setup must not be exposed as ordinary logged command arguments. |
| Combination | CombinationNumber |
CombinationPadlock only; exactly four digits. |
| Authorized keyholders | MemberNumberListKeys |
HighSecurityPadlock only; BC serializes the member-number list as a string. |
| Lock provenance / runtime | LockedBy, LockMemberNumber, LockMemberName, LockMessage, LockPickSeed, Effect |
BC-owned state. Never accept these as caller-provided generic options. LockMessage also has feature-specific uses. |
MemberNumberList and MemberNumberListKeys are distinct BC properties with
different semantics. Their meaning must not be collapsed into one generic
“allowed users” option.
Keep the feature-facing contract in core/ and BC-specific capability
discovery/validation in the BC adapter. Features must not import each other or
construct packets. The appearance feature remains responsible for user intent,
authorization, and presentation; it does not own lock rules or BC mutation
mechanics.
The CharacterAppearanceApi and AppearanceMutation model the general
appearance operations. CharacterAppearanceLockApi adds a separate,
ephemeral-secret input for credentials. BcAppearanceAction lives in the BC
adapter and implements both API ports, keeping the executor feature-neutral
while retaining its per-character queue, observation wait, cancellation, and
single ActionCoordinator journal lifecycle.
Add a BC lock capability catalog beside the existing BC asset catalog. Derive
basic facts from pinned asset metadata (IsLock, AllowLock,
AllowLockType, OwnerOnly, LoverOnly, FamilyOnly, Enable,
ExclusiveUnlock, PickDifficulty, MaxTimer, RemoveTimer, and baseline
properties). Add a reviewed support policy for browser-specific hooks and
special cases. Discovery of an upstream asset must not automatically enable
headless mutation: unknown or unresolved behavior fails closed.
Use a typed, per-lock option schema at the BC boundary. The public request uses semantic fields such as duration, remove-on-expiry, timer presentation, password hint, or keyholder members; the adapter translates those fields to BC property names. Validate exact type, bounds, target relationship evidence, item lockability, selected typed/modular option, existing lock state, and special lock preconditions before dispatch. Reject replacing a different lock or silently reconfiguring a lock. If same-lock renewal is ever supported, make it an explicit policy with a test.
Do not persist or journal passwords, combinations, or appearance payloads.
Never place a secret in a command string, itemset document, action desired
metadata, debug output, or exception text. Journal only reviewed non-secret
lock intent. BC observations can contain lock properties; keep them in memory
for comparison and redact them from logs/journals.
classDiagram
direction LR
class AppearanceFeature {
+request appearance lock
+authorize caller
}
class FutureAppearanceWorkflow {
+request appearance lock
}
class CharacterAppearanceApi {
<<core port>>
+execute(member, mutation) ActionOutcome
}
class CharacterAppearanceLockApi {
<<core port; secrets are ephemeral>>
+executeLock(member, request, secrets?) ActionOutcome
}
class BcAppearanceAction {
<<shared technical implementation>>
-per-character queue
+execute(member, mutation) ActionOutcome
+executeLock(member, request, secrets?) ActionOutcome
}
class BcAppearanceCodec {
+plan(character, mutation, actor)
+matches(observed, desired)
}
class BcLockCapabilityCatalog {
<<pinned BC metadata plus reviewed support policy>>
+get(type) LockCapability
+validateOptions(type, options)
}
class ActionCoordinator {
+executeObserved(request) ActionOutcome
}
class BcClient {
<<transport adapter>>
+updateCharacterAppearance(...)
+getAppearanceObservation(member)
}
class CompositionRoot {
+construct shared services
+inject ports into plugins
}
AppearanceFeature --> CharacterAppearanceApi
FutureAppearanceWorkflow --> CharacterAppearanceApi
CharacterAppearanceApi <|.. BcAppearanceAction
CharacterAppearanceLockApi <|.. BcAppearanceAction
BcAppearanceAction --> BcAppearanceCodec
BcAppearanceAction --> BcLockCapabilityCatalog
BcAppearanceAction --> ActionCoordinator
BcAppearanceAction --> BcClient
CompositionRoot --> BcAppearanceAction : constructs and injects
sequenceDiagram
actor Feature
participant API as CharacterAppearanceApi
participant Action as Shared BcAppearanceAction
participant Catalog as BcLockCapabilityCatalog
participant Codec as BcAppearanceCodec
participant Journal as ActionCoordinator
participant BC as BcClient / BC
alt credential-free lock
Feature->>API: execute(lock mutation)
else password or combination lock
Feature->>API: executeLock(request, ephemeral secrets)
end
API->>Action: validated mutation and separate ephemeral secrets
Action->>BC: query interaction/item access
BC-->>Action: allowed / denied / unknown
Action->>BC: read latest observed appearance
Action->>Catalog: resolve type and validate options
Catalog-->>Action: supported capability or explicit rejection
Action->>Codec: validate item, selected option, permissions, existing lock
Codec-->>Action: planned full appearance bundle
Action->>Journal: requested lifecycle
Action->>BC: guarded full appearance update
BC-->>Action: later appearance observation (if received)
Action->>Journal: observed / timed_out_unobserved / failed
Action-->>Feature: ActionOutcome
stateDiagram-v2
[*] --> ValidateRequest
ValidateRequest --> Rejected: unknown lock / malformed options
ValidateRequest --> CheckObservedItem: valid request
CheckObservedItem --> Rejected: missing / occupied / not lockable
CheckObservedItem --> CheckBCPermission: current observed item valid
CheckBCPermission --> Rejected: denied / unknown / relationship unsupported
CheckBCPermission --> Plan: allowed
Plan --> AlreadySatisfied: observed lock already matches
Plan --> JournalRequested: planned mutation
JournalRequested --> Rejected: journal unavailable
JournalRequested --> Dispatch: journaled
Dispatch --> AwaitObservation: packet emitted
Dispatch --> Failed: cancelled / stale appearance
AwaitObservation --> Observed: later full appearance matches
AwaitObservation --> TimedOutUnobserved: no matching evidence
AwaitObservation --> Failed: disconnect / target leaves / stop
An observed result means room-state convergence, not proof that BC persisted
the character profile. No response must remain timed_out_unobserved; do not
retry a potentially applied appearance mutation against stale state.
BcLockCapabilityCatalog discovers all 18 source-declared IsLock assets.
Discovery is deliberately separate from mutation policy: the first enabled
types are MetalPadlock, IntricatePadlock, TimerPadlock,
TimerPasswordPadlock, ExclusivePadlock, CombinationPadlock, and
PasswordPadlock. Other locks remain inspectable but are rejected with explicit
reasons until their relationship, keyholder, credential, portal, or inventory
semantics are reviewed. Intricate and Exclusive lock application is supported;
BC remains authoritative for their specialized key and unlock behavior.
Lock requests use AppearanceLockSelection with generic semantic options.
Duration is relative milliseconds and is checked against the selected lock’s
pinned MaxTimer; the adapter maps it to BC’s absolute RemoveTimer. Itemsets
can configure timer duration, RemoveItem, and ShowTimer only when the lock
policy allows them. Expiry overrides are converted to durations for any
supported timer lock.
Password and combination input travels only through the separate
executeLock(..., secrets) method. Explicit password/combination locks are not
itemset-supported. TimerPasswordPadlock may receive a cryptographically
generated, ephemeral password so Bunny itemsets do not contain credentials.
Secrets and full appearance properties are excluded from journal metadata.
Unit and fake-socket integration coverage verifies the contract, redaction,
option mapping, and all-18 discovery. Intricate and Exclusive lock application
passed live BC qualification; this does not establish account-profile
persistence.
Owner, lover, family, high-security, mistress, Pandora, safeword, portal-specific,
and other specialized locks remain unsupported. Do not broaden mutation support
by accepting arbitrary Property fields or assuming that a syntactically valid
appearance bundle will pass BC server-side validation.
This inventory’s original source snapshot was Bondage-College
1eb7f9e290c7f4f17d5f48f213edd2235fd93003; the prototype now pins
5eb495c5ced4ee92d40385b7521e6ca63ace12e5 (R133Beta1). The lock names and fields
come from the AssetLockType declaration,
the ItemMisc lock asset definitions,
the extended lock baselines,
the browser lock application and eligibility rules,
the appearance lock validation and timer bounds,
and BC’s unlock/key rules.
The existing prototype guarantees referenced above are documented in the appearance foundation and the BC API plane.