Implement appearance and current outfit services (#65)
Some checks failed
Native code generation / deterministic (push) Failing after 2m19s
Imaging and meshing gate / native (push) Failing after 1m26s
Native Rust workspace compile / compile (push) Failing after 2m11s

This commit is contained in:
2026-08-10 08:58:29 +00:00
parent 52f62d8c39
commit a9927fcfcb
13 changed files with 2900 additions and 242 deletions

View File

@@ -0,0 +1,87 @@
#!/usr/bin/env python3
"""Audit issue 65's wearable, attachment, COF, and policy boundary."""
from __future__ import annotations
from pathlib import Path
import re
import generate_api_shims
ROOT = Path(__file__).resolve().parents[1]
APPEARANCE = ROOT / "crates" / "libremetaverse" / "src" / "appearance_manager.rs"
COF = ROOT / "crates" / "libremetaverse" / "src" / "current_outfit.rs"
CLIENT = ROOT / "crates" / "libremetaverse" / "src" / "client_core.rs"
COMPAT = ROOT / "tests" / "compat" / "tests"
LINK_TESTS = ROOT / "crates" / "libremetaverse" / "src" / "batch_link_internal_semantics.rs"
DOC = ROOT / "docs" / "appearance.md"
STUB_RE = re.compile(r"\b(?:not_implemented|unimplemented_api)\b|\b(?:todo|unimplemented)!\s*\(")
REQUIRED_TYPES = {
"T:LibreMetaverse.AppearanceManager",
"T:LibreMetaverse.Appearance.CompositeCurrentOutfitPolicy",
"T:LibreMetaverse.Appearance.CurrentOutfitFolder",
}
REQUIRED_MEMBERS = {
"M:LibreMetaverse.Appearance.CurrentOutfitFolder.AddToOutfitAsync(System.Collections.Generic.List{LibreMetaverse.InventoryItem},System.Boolean,System.Threading.CancellationToken)",
"M:LibreMetaverse.Appearance.CurrentOutfitFolder.AttachAsync(LibreMetaverse.InventoryItem,LibreMetaverse.AttachmentPoint,System.Boolean,System.Threading.CancellationToken)",
"M:LibreMetaverse.Appearance.CurrentOutfitFolder.DetachAsync(LibreMetaverse.InventoryItem,System.Threading.CancellationToken)",
"M:LibreMetaverse.Appearance.CurrentOutfitFolder.GetCurrentOutfitLinksAsync(System.Threading.CancellationToken)",
"M:LibreMetaverse.Appearance.CurrentOutfitFolder.GetWornAtAsync(LibreMetaverse.WearableType,System.Threading.CancellationToken)",
"M:LibreMetaverse.Appearance.CurrentOutfitFolder.ReplaceOutfitAsync(LibreMetaverse.UUID,System.Threading.CancellationToken)",
"M:LibreMetaverse.AppearanceManager.Attach(LibreMetaverse.InventoryItem,LibreMetaverse.AttachmentPoint,System.Boolean)",
"M:LibreMetaverse.AppearanceManager.GetAttachmentsByAttachmentPointAsync(System.Threading.CancellationToken)",
"M:LibreMetaverse.AppearanceManager.GetFolderWearablesAsync(LibreMetaverse.UUID,System.Threading.CancellationToken)",
"M:LibreMetaverse.AppearanceManager.SendOutfitToCurrentSimulatorAsync(System.Threading.CancellationToken)",
}
def require_markers(path: Path, markers: tuple[str, ...]) -> None:
text = path.read_text()
missing = [marker for marker in markers if marker not in text]
if missing:
raise SystemExit(f"{path.name}: audit evidence missing: " + ", ".join(missing))
def main() -> None:
native = set(generate_api_shims.NATIVE_TYPES) | set(generate_api_shims.NATIVE_DECLARATIONS)
missing_types = sorted(REQUIRED_TYPES - native)
if missing_types:
raise SystemExit("issue 65 native types missing: " + ", ".join(missing_types))
missing_members = sorted(REQUIRED_MEMBERS - set(generate_api_shims.NATIVE_MEMBER_BODIES))
if missing_members:
raise SystemExit("issue 65 native members missing: " + ", ".join(missing_members))
for source in (APPEARANCE, COF):
if STUB_RE.search(source.read_text()):
raise SystemExit(f"issue 65 owned Rust stubs remain in {source.name}")
require_markers(APPEARANCE, (
"MAX_WEARABLE_LAYERS", "MAX_FOLDER_TRAVERSAL",
"AgentIsNowWearing", "RezSingleAttachmentFromInv",
"DetachAttachmentIntoInv", "permissions.everyone_mask",
"native_attachments_at", "emit_with",
"attachment_packet_and_replacement_state_preserve_inventory_fields",
"wearable_layers_are_bounded_and_bodyparts_replace_by_slot",
))
require_markers(COF, (
"MAX_CLOTHING_LAYERS", "MAX_ANCESTRY_DEPTH", "shadow_links",
"tokio::sync::Semaphore", "token.cancelled()", "snapshot()",
"create_links", "remove_links", "native_resolve_inventory_link",
"failed_replace_keeps_old_shadow_state_and_records_compensation",
"attach_creates_cof_link_before_network_execution",
"attachment_replace_removes_displaced_link_after_new_attachment",
"cancelled_operation_does_not_reach_backend",
))
require_markers(CLIENT, ("native_appearance", "native_set_appearance"))
require_markers(COMPAT / "current_outfit_folder_semantics.rs", ("parity-case", "get_current_outfit_links"))
require_markers(COMPAT / "current_outfit_policy_semantics.rs", ("parity-case", "report_item_change"))
require_markers(COMPAT / "appearance_semantics.rs", ("wearable_type_to_asset_type", "last_update_received_cof_version"))
require_markers(LINK_TESTS, ("get_cof_link_description", "clothing_wearable"))
require_markers(DOC, ("60", "256", "create replacement links before removing old links", "no state or subscriber lock", "compensation"))
print("issue 65 audit: native wearable/attachment state, transactional COF links, policy snapshots, cancellation, documentation, and focused fake/compatibility evidence are present")
if __name__ == "__main__":
main()