from __future__ import annotations import json import re from src.api.v1.platform.tenants import ListTenantsResponse, _tenant_readback_fallback from src.services.platform_operator_service import build_tenant_asset_inventory FORBIDDEN_PUBLIC_MARKERS = [ "Vibe" + "Work", "Agent " + "Bounty " + "Protocol", "agent-" + "bounty-" + "protocol", "AWOOOI / " + "AwoooP / " + "IwoooS", "Tsen" + "Yang Website", "Bitan " + "Pharmacy", "repo_owner_namespace_redacted=true", "raw_repository_namespace_visible=false", "public_api_raw_repo_namespace_allowed=false", "read_only_inventory_only=true", "runtime_execution_authorized=false", "action_buttons_allowed=false", ] def test_tenant_asset_inventory_merges_products_routes_and_repos() -> None: tenants = [ { "project_id": "awoooi", "display_name": "AWOOOI", "migration_mode": "shadow", "budget_limit_usd": None, "is_active": True, "created_at": "2026-06-14T00:00:00+08:00", } ] inventory = build_tenant_asset_inventory(tenants) summary = inventory["summary"] assert inventory["schema_version"] == "awooop_tenant_asset_inventory_v1" assert summary["tenant_table_count"] == 1 assert summary["product_surface_count"] >= 16 assert summary["public_route_count"] >= 31 assert summary["source_candidate_repo_count"] == 10 assert summary["source_in_scope_repo_count"] == 9 assert summary["source_primary_ready_count"] == 0 assert summary["owner_response_accepted_count"] == 0 assert summary["runtime_gate_count"] == 0 assert summary["action_button_count"] == 0 product_ids = {item["product_id"] for item in inventory["products"]} assert { "PRD-001", "PRD-002", "PRD-003", "PRD-004", "PRD-005", "PRD-006", "PRD-007", "PRD-008", "PRD-010", "PRD-011", "PRD-012", "PRD-013", "PRD-014", }.issubset(product_ids) assert all(re.fullmatch(r"PRD-\d{3}", item["project_id"]) for item in inventory["products"]) assert all(item["source_keys"] == [] or all(key.startswith("SRCREF-") for key in item["source_keys"]) for item in inventory["products"]) route_domains = {item["domain"] for item in inventory["public_routes"]} assert { "awoooi.wooo.work", "stock.wooo.work", "bitan.wooo.work", "mo.wooo.work", "vibework.wooo.work", "agent.wooo.work", "2026fifa.wooo.work", "design.wooo.work", "n8n.wooo.work", "grist.wooo.work", "vault.wooo.work", "ollama.wooo.work", "tsenyang.com", "tsenyang.wooo.work", }.issubset(route_domains) source_repos = {item["github_repo"] for item in inventory["source_repos"]} source_scope_ids = {item["source_scope_id"] for item in inventory["source_repos"]} assert "SRC-008" in source_scope_ids assert "SRC-009" in source_scope_ids assert "SRC-010" in source_scope_ids assert all(re.fullmatch(r"SRC-\d{3}", repo) for repo in source_repos) assert all(item["source_namespace_redacted"] for item in inventory["source_repos"]) inventory_payload = json.dumps(inventory, ensure_ascii=False) assert "owenhytsai" not in inventory_payload assert "nexu-io" not in inventory_payload assert "blocked_waiting_" not in inventory_payload assert "observe_scope_review" not in inventory_payload assert all(marker not in inventory_payload for marker in FORBIDDEN_PUBLIC_MARKERS) assert "只讀資產台帳" in " ".join(inventory["boundaries"]) assert all("=" not in boundary for boundary in inventory["boundaries"]) assert {item["risk"] for item in inventory["source_repos"]}.issubset( {"high", "medium", "low", "unknown"} ) assert {item["readiness_state"] for item in inventory["source_repos"]}.issubset( { "need_refs_evidence", "need_target_decision", "need_internal_remote_decision", "need_scope_review", "need_owner_evidence", } ) assert all(item["runtime_gate_count"] == 0 for item in inventory["source_repos"]) assert all(item["action_button_count"] == 0 for item in inventory["public_routes"]) assert all(item["runtime_gate_count"] == 0 for item in inventory["products"]) def test_tenant_response_model_keeps_asset_inventory_contract() -> None: tenant = { "project_id": "awoooi", "display_name": "AWOOOI", "migration_mode": "shadow", "budget_limit_usd": None, "is_active": True, "created_at": "2026-06-14T00:00:00+08:00", } inventory = build_tenant_asset_inventory([tenant]) response = ListTenantsResponse.model_validate( { "tenants": [tenant], "total": 1, "asset_inventory": inventory, } ) assert response.asset_inventory.summary.product_surface_count >= 16 assert response.asset_inventory.summary.runtime_gate_count == 0 assert response.asset_inventory.products[0].runtime_gate_count == 0 response_payload = response.model_dump_json() assert "owenhytsai" not in response_payload assert "nexu-io" not in response_payload assert all(marker not in response_payload for marker in FORBIDDEN_PUBLIC_MARKERS) assert response.asset_inventory.source_repos[0].source_namespace_redacted is True def test_tenant_readback_fallback_keeps_response_model_no_write_contract() -> None: response = ListTenantsResponse.model_validate(_tenant_readback_fallback()) assert response.tenants[0].project_id == "awoooi" assert response.tenants[0].migration_mode == "readback_degraded" assert response.asset_inventory.mode == "readback_degraded_ai_controlled_repair" assert response.asset_inventory.summary.tenant_table_count == 0 assert response.asset_inventory.products == [] assert response.asset_inventory.public_routes == [] assert response.asset_inventory.source_repos == [] assert "does not modify" in " ".join(response.asset_inventory.boundaries)