Files
MetaCrate/docs/world-services.md
Chili Palmer 763e9e5044
All checks were successful
Native code generation / deterministic (push) Successful in 15m57s
Imaging and meshing gate / native (push) Successful in 5m16s
Native Rust workspace compile / compile (push) Successful in 5m11s
Implement estate and marketplace services (#73)
2026-08-10 19:25:31 +00:00

4.6 KiB

Estate, experience, marketplace, and reporting services

These services keep protocol decisions and cached state separate from their network boundaries. Folder classification and listing validation are pure inventory operations. Estate access-list codes, restart-day conversion, and experience permission extraction can likewise be evaluated without a live grid. Network methods use the current simulator only when a packet or capability request is required.

Estate administration

GridClient::estate() returns a client-cached EstateTools; clones share the same subscriptions, events, disposal state, and live-operation gate. Incoming EstateOwnerMessage, covenant, and land-stat packets are bounded and decoded into typed access-list, experience-list, estate-info, covenant, top-script, and top-collider events. Estate owner messages retain their upstream method names, parameter ordering, access-delta values, invoice UUID, and agent/session IDs.

Region schedules use the RegionSchedule capability. Daily schedules encode as D; weekly schedules encode as W with SMTWRFA day letters, and times are whole seconds. Simulator console commands subscribe for SimConsoleResponse before posting to SimConsoleAsync; the HTTP response body is intentionally ignored. The event wait observes both the caller's cancellation token and the requested timeout.

Terrain uploads are staged in AssetManager before the owner message is sent. The normal transfer-request and transfer-confirmation path then serves the staged bytes, and a failed owner message removes the pending transfer.

Estate packet mutations and mutating capabilities are disabled by default. Call EstateTools::enable_live_mutations() only after authenticating the operator, checking estate-manager authority, showing the exact target and operation, and obtaining confirmation. This gate covers access changes, returns, teleports, restarts, terrain changes/uploads, console commands, and region or estate settings. Test capabilities under the reserved .invalid domain remain usable by offline fixtures without enabling live mutations.

Experience preferences

Experience preferences use the simulator's named capabilities and preserve the experiences (allow), blocked (block), and absent (forget) decisions. Estate experience replies preserve the blocked, trusted, and allowed list boundaries reported by the owner message. Requests and mutations propagate cancellation and apply input/body limits before parsing or publishing state.

Marketplace

MarketplaceFolderClassifier derives listing-root, listing, version, stock, and content roles entirely from an inventory snapshot. It validates missing or multiple version folders and counts direct stock items without performing network I/O.

MarketplaceManager keeps listing-ID and inventory-folder indexes in sync and publishes synchronized, changed, and error events after committing cache updates. Fetch is read-only. Create, delete, activate, and deactivate use the MarketplaceListings capability and are disabled for live endpoints until enable_live_mutations() is called. Applications should confirm price, quantity, folder identity, and listing state immediately before opting in. Offline .invalid fixtures exercise the same payload code without contacting a service.

Abuse and user reports

GridClient::user_reports() fetches localized abuse categories from AbuseCategories; language tags are restricted to ASCII letters, digits, and hyphens before the lc query is appended. Reports select SendUserReportWithScreenshot when a screenshot UUID is present and otherwise use SendUserReport. Capability payloads preserve the upstream fields and allow the simulator to infer its own region; failed capability submissions fall back to the legacy UserReport packet.

Report submission is a privileged, privacy-sensitive action and is disabled for live endpoints until UserReportService::enable_live_submissions() is called. Obtain user confirmation, review the summary/details and identifiers, and avoid logging report bodies. Null report types and oversized text or region names are rejected. Discovery and submission propagate cancellation; recorded .invalid fixtures remain available for offline payload verification.

Validation

The focused suite uses synthetic packets and in-memory HTTP handlers. It covers owner-message experience lists, exact console event/timeout behavior, restart schedule conversion, experience permissions, marketplace classifications and CRUD payloads/events, localized abuse categories, report capability selection, exact report LLSD, cancellation, and live-operation gates. No live grid or Internet service is required.