# Native RLV protocol layer

`libremetaverse-rlv` implements the protocol and pure state boundary for the
Restrained Love Viewer support in the pinned LibreMetaverse snapshot. The
side-effect-free parser converts one bounded chat message into typed commands.
Independent, thread-safe managers store restrictions and evaluate inventory,
folder locks, camera limits, blacklists, and permissions without performing
network I/O. The callback-driven service then executes those typed decisions
through explicit host adapters.

## Message contract

An input begins with `@` and contains at most 128 comma-separated commands in
at most 64 KiB. A command is either the case-insensitive bare `clear` command,
or has the form `behavior[:option]=parameter`. The first colon and first equals
sign are structural. Empty commands, behavior names, or parameters are
rejected.

The parser preserves the original behavior and parameter spelling, option text,
sender identity and name, and the exact byte span of each command. It also
provides lowercase behavior and parameter fields for protocol dispatch. Option
text is never globally trimmed or lowercased: folder paths, query separators,
setting values, role names, and other opaque strings retain their bytes. Only
an individual typed field applies the conversion required by the reference,
such as case-insensitive attachment aliases or .NET-style whitespace trimming
for a number.

Parameters select one of three families:

- `force` produces a typed `RlvAction` with validated UUID, numeric, folder,
  attachment, wearable, setting, group, and teleport operands.
- `n`/`add` and `y`/`rem` produce typed add/remove restrictions. The complete
  table of 119 behavior spellings is exposed as `RLV_RESTRICTION_NAMES`.
- a nonzero signed decimal channel produces a typed `RlvQuery`, including
  camera, inventory, outfit, path, status, version, group, and environment
  variants.

Aliases remain explicit. `FarTouch` canonicalizes to `TouchFar` in a mapped
`RlvRestriction`, while `OriginalBehavior` retains `FarTouch`. The 56 pinned
attachment spellings and 16 wearable spellings are case-insensitive but are
not whitespace-normalized. `root` maps to the avatar-center attachment point,
matching the reference. Secure restriction exception rules and value-sensitive
equality/hash behavior are implemented by the native mapped
`RlvRestriction`; `RlvCommon` implements the last-recognized attachment tag
rule used for inventory item names.

## Errors and resource limits

`RlvParseError` reports a stable `RlvParseErrorKind`, zero-based command index,
and half-open byte span. Categories distinguish missing prefix or separators,
empty fields, unknown actions/restrictions/queries, invalid UUIDs, numbers and
typed options, zero query channels, and resource-limit failures. Parsing is
linear in the message size after bounded command counting. It performs no I/O,
does not wait, and does not retain references to caller input.

The focused malformed corpus includes deterministic deletion, replacement, and
insertion mutations of actions, restrictions, queries, UUIDs, aliases, and
multi-command messages. Every mutation must return a value or a positioned
error without panicking. The limits apply before large parser allocations.

## State, inventory, and permission contract

`RlvSharedFolder` and `RlvInventoryItem` preserve the reference semantics of
their C# counterparts. `InventoryMap` walks a bounded shared-inventory tree and
publishes immutable dictionary/list membership snapshots. Path lookup handles
hidden/private prefixes, exact names containing forward slashes, and the
reference implementation's longest matching segment rule. Lookup by item,
attached prim, attachment point, and wearable type does not call a client or
inventory service.

`RlvRestrictionManager` deduplicates exact restrictions, retains deterministic
insertion order, removes all state for selected object sources, and rebuilds
immutable locked-folder snapshots when either restrictions or inventory
changes. Recursive and non-recursive attach/detach locks support sender-item,
attachment, wearable, and path targets plus their exception variants. Update
handlers run only after manager locks are released, so callbacks can safely
query the manager again. Poisoned synchronization primitives recover their
owned state instead of making later reads fail.

`RlvPermissionsService` evaluates simple restrictions, secure and explicit
target rules, permissive exception precedence, IM/chat/channel behavior,
teleport limits, edit/touch/hover decisions, shared and unshared wear, and
folder attachment locks. Camera aggregation applies the reference min/max,
clamping, averaging, alias, texture, and lock rules. The case-insensitive
blacklist returns a sorted snapshot. These providers are deterministic and
thread-safe with no network access. Object-source cleanup snapshots the
affected restrictions and notification listeners, then invokes the injected
action callback after releasing every manager lock.

## Callback and service contract

`RlvService` owns bounded chat and instant-message dispatch, typed action and
get-request routing, restriction lifecycle notifications, and inventory,
attachment, outfit, public-message, sit, and unsit reports. A chat message is
rejected before dispatch when it exceeds the parser's 64 KiB or 128-command
limits. Multi-command processing retains source order and continues after a
well-formed command returns `false`, matching the reference aggregate result.
Blacklist replies, query channels, version strings, restriction messages, and
case-sensitive general notification filters preserve the pinned behavior.

Hosts implement the `IRlvQueryCallbacks` and `IRlvActionCallbacks` `Send + Sync`
traits. Query adapters expose snapshots from the completed inventory and agent
services; action adapters perform attachment, outfit, camera, group, movement,
teleport, chat, and reply operations through those services instead of
reaching into their state. The safe default adapters reproduce the reference
query values and no-op actions while still observing cancellation. Every host
future is awaited only after service and restriction-manager locks have been
released, so recording callbacks may synchronously inspect service state.

The command processor refreshes `InventoryMap` through the query boundary and
publishes the same snapshot to `RlvPermissionsService` before folder or item
decisions. Attachment requests are value objects with a stable cross-platform
hash. Folder walks preserve deterministic order, skip private and hidden
content where required, deduplicate linked items, honor `nostrip`, body-part,
link-exception, and recursive-lock rules, and never manufacture an action for
an invalid target. Cancellation is checked before processing, reports,
inventory refreshes, each multi-command element, and every callback.

## Reproducible verification

Run the issue-owned checks with one build job:

```sh
CARGO_BUILD_JOBS=1 cargo test -p libremetaverse-rlv --locked
CARGO_BUILD_JOBS=1 cargo test -p libremetaverse-compat-tests --test rlv_common_semantics --locked
CARGO_BUILD_JOBS=1 cargo test -p libremetaverse-compat-tests --test rlv_inventory_map_semantics --locked
CARGO_BUILD_JOBS=1 cargo test -p libremetaverse-compat-tests --test rlv_query_basics_semantics --locked
CARGO_BUILD_JOBS=1 cargo test -p libremetaverse-compat-tests --test rlv_attach_commands_semantics --locked
CARGO_BUILD_JOBS=1 cargo test -p libremetaverse-compat-tests --test rlv_notify_semantics --locked
CARGO_BUILD_JOBS=1 cargo clippy -p libremetaverse-rlv --all-targets --locked -- -D warnings
RUSTDOCFLAGS='-D warnings' CARGO_BUILD_JOBS=1 cargo doc -p libremetaverse-rlv --no-deps --locked
python3 tools/check_milestone_10_issue_78.py
python3 tools/check_milestone_10_issue_79.py
python3 tools/check_milestone_10_issue_80.py
```

The complete issue-owned compatibility slice contains 616 translated RLV
cases across 24 test binaries. These commands are cross-platform. The Gitea
workflow runs the audit and workspace compile on `ubuntu-latest`.
