Files
MetaCrate/tools/check_milestone_10_issue_79.py
Chili Palmer fb8b17b02d
Some checks failed
CI / required (push) Failing after 3m47s
Consolidate required CI gate (#115)
2026-08-12 21:56:56 +00:00

124 lines
5.2 KiB
Python

#!/usr/bin/env python3
"""Audit issue 79's native RLV state, inventory, lock, and permission boundary."""
from __future__ import annotations
import json
import re
from pathlib import Path
import generate_api_shims
ROOT = Path(__file__).resolve().parents[1]
SOURCE = ROOT / "crates" / "libremetaverse-rlv" / "src" / "state.rs"
GENERATED = ROOT / "crates" / "libremetaverse-rlv" / "src" / "generated.rs"
TESTS = ROOT / "crates" / "libremetaverse-rlv" / "tests" / "state_semantics.rs"
COMPAT = ROOT / "tests" / "compat" / "tests" / "rlv_inventory_map_semantics.rs"
DOC = ROOT / "crates" / "libremetaverse-rlv" / "README.md"
WORKFLOW = ROOT / ".gitea" / "workflows" / "ci.yml"
CATALOG = ROOT / "api" / "public-api.json"
STUB_RE = re.compile(r"\b(?:not_implemented|unimplemented_api)\b|\b(?:todo|unimplemented)!\s*\(")
TYPES = {
"T:LibreMetaverse.RLV.CameraRestrictions": "crate::state::CameraRestrictions",
"T:LibreMetaverse.RLV.CameraSettings": "crate::state::CameraSettings",
"T:LibreMetaverse.RLV.EventArguments.RestrictionUpdatedEventArgs":
"crate::state::RestrictionUpdatedEventArgs",
"T:LibreMetaverse.RLV.InventoryMap": "crate::state::InventoryMap",
"T:LibreMetaverse.RLV.LockedFolderPublic": "crate::state::LockedFolderPublic",
"T:LibreMetaverse.RLV.RlvBlacklist": "crate::state::RlvBlacklist",
"T:LibreMetaverse.RLV.RlvInventoryItem": "crate::state::RlvInventoryItem",
"T:LibreMetaverse.RLV.RlvPermissionsService": "crate::state::RlvPermissionsService",
"T:LibreMetaverse.RLV.RlvRestrictionManager": "crate::state::RlvRestrictionManager",
"T:LibreMetaverse.RLV.RlvSharedFolder": "crate::state::RlvSharedFolder",
}
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 catalog_members() -> set[str]:
catalog = json.loads(CATALOG.read_text())
assembly = next(
value for value in catalog["assemblies"]
if value["identity"]["name"] == "LibreMetaverse.RLV"
)
return {
member["doc_id"]
for api_type in assembly["types"]
if api_type["doc_id"] in TYPES
for member in api_type["members"]
}
def generated_type_block(text: str, doc_id: str) -> str:
marker = f"/// C# type: `{doc_id}`."
start = text.find(marker)
if start < 0:
raise SystemExit(f"generated declaration is missing for {doc_id}")
next_type = text.find("/// C# type:", start + len(marker))
return text[start:] if next_type < 0 else text[start:next_type]
def main() -> None:
for api_type, declaration in TYPES.items():
if generate_api_shims.NATIVE_DECLARATIONS.get(api_type) != declaration:
raise SystemExit(f"issue 79 native declaration is missing for {api_type}")
members = catalog_members()
missing = sorted(members - set(generate_api_shims.NATIVE_MEMBER_BODIES))
if missing:
raise SystemExit("issue 79 native members missing: " + ", ".join(missing))
source = SOURCE.read_text()
if STUB_RE.search(source):
raise SystemExit("issue 79 owned Rust stubs remain in state.rs")
generated = GENERATED.read_text()
for api_type in TYPES:
if STUB_RE.search(generated_type_block(generated, api_type)):
raise SystemExit(f"issue 79 owned generated stubs remain for {api_type}")
require_markers(SOURCE, (
"MAX_RLV_INVENTORY_FOLDERS", "MAX_RLV_INVENTORY_ITEMS",
"MAX_RLV_RESTRICTIONS", "pub struct InventoryMap",
"pub struct RlvRestrictionManager", "pub struct RlvPermissionsService",
"pub struct CameraRestrictions", "pub struct LockedFolderPublic",
"pub struct RlvBlacklist", "fn build_locked_folders",
"fn secure_allowed", "fn rebuild_locked_folders", "fn emit",
"state.revision", "Arc<RwLock", "ImmutableDictionary", "CancellationToken",
))
require_markers(TESTS, (
"dispatches_after_unlocking", "concurrent_independent_sources",
"stale_revision", "counts_repeated_inputs_before_deduplication",
"blacklist_is_case_insensitive", "camera_restrictions_apply",
"constructor_field_order", "secure_rules_take_precedence",
"recursive_folder_locks", "snapshots remain immutable",
))
require_markers(COMPAT, (
"try_get_folder_when_name_contains_slash",
"try_get_folder_prefers_exact_slash_match",
"try_get_folder_skips_hidden_folder",
"find_folders_containing_by_prim_id",
"find_folders_containing_by_attachment_point_single_result",
"find_folders_containing_by_wearable_type",
))
require_markers(DOC, (
"pure state boundary", "immutable dictionary/list membership snapshots",
"after manager locks are released", "secure and explicit", "no network",
"ubuntu-latest",
))
require_markers(WORKFLOW, ("required-gate",))
print(
"issue 79 audit: native restriction state, inventory maps, recursive locks, "
"camera aggregation, blacklist, permission precedence, concurrency evidence, "
"compatibility tests, and docs are present"
)
if __name__ == "__main__":
main()