"""Read-only inventory for external MCP/RAG absorption into internal control planes.""" from __future__ import annotations import os import hashlib import json from copy import deepcopy from datetime import datetime, timezone from typing import Any from zoneinfo import ZoneInfo POLICY = "read_only_external_mcp_rag_integration_readback_v1" PUBLIC_FEDERATION_SCHEMA_VERSION = "ewoooc_mcp_federation_receipt_v1" PUBLIC_FEDERATION_POLICY = "public_aggregate_read_only_mcp_federation_v1" TAIPEI_TZ = ZoneInfo("Asia/Taipei") _FEDERATED_PRODUCTS = ( { "product_id": "ewoooc", "canonical_repo": "wooo/ewoooc", "runtime_role": "mcp_rag_automation_source_plane", }, { "product_id": "momo-pro-system", "canonical_repo": "wooo/momo-pro-system", "runtime_role": "commerce_runtime_consumer_plane", }, ) def _enabled(value: str | None) -> bool: return str(value or "").strip().lower() in {"1", "true", "yes", "on"} def _controlled_apply_boundary() -> dict[str, bool]: return { "network_call": False, "db_write": False, "secret_read": False, "production_price_write": False, "external_side_effect": False, } def _public_operation_boundaries() -> dict[str, bool]: """V-New: 公開 receipt 只允許無副作用的聚合狀態讀回。""" return { "read_only_observation_allowed": True, "network_call_allowed": False, "db_write_allowed": False, "secret_read_allowed": False, "external_tool_call_allowed": False, "rag_write_allowed": False, "production_price_write_allowed": False, "request_or_response_body_storage_allowed": False, } def _safe_mcp_summary(snapshot: dict[str, Any]) -> dict[str, Any]: servers = snapshot.get("servers") servers = servers if isinstance(servers, dict) else {} registry = snapshot.get("tool_registry") registry = registry if isinstance(registry, dict) else {} tool_count = 0 for server_map in registry.values(): if not isinstance(server_map, dict): continue for tools in server_map.values(): if isinstance(tools, (list, tuple, set)): tool_count += len(tools) return { "enabled": snapshot.get("enabled") is True, "server_count": len(servers), "server_ids": sorted(str(server_id) for server_id in servers), "caller_count": int(snapshot.get("caller_count") or 0), "tool_count": tool_count, } def _safe_rag_summary(snapshot: dict[str, Any]) -> dict[str, Any]: model = str(snapshot.get("embedding_model") or "") return { "enabled": snapshot.get("enabled") is True, "vector_store": str(snapshot.get("vector_store") or "pgvector"), "embedding_model": model, "embedding_dim": int(snapshot.get("embedding_dim") or 0), "embedding_signature": str(snapshot.get("embedding_signature") or ""), "embedding_version_state": ( "floating_tag_detected" if model.endswith(":latest") else "explicit_or_unknown" ), } def _safe_pixelrag_summary(snapshot: dict[str, Any]) -> dict[str, Any]: return { "enabled": snapshot.get("enabled") is True, "platform_count": int(snapshot.get("platform_count") or 0), "platforms": sorted( str(platform) for platform in snapshot.get("platforms") or [] ), "visual_rag_stage": str( snapshot.get("visual_rag_stage") or "unavailable" ), "formal_product_write_allowed": False, } def compute_public_federation_receipt_fingerprint( receipt: dict[str, Any], ) -> str: """Return the verifier-recomputable hash for normalized public fields.""" covered = { key: value for key, value in receipt.items() if key not in {"receipt_id", "observed_at", "integrity"} } canonical = json.dumps( covered, ensure_ascii=False, sort_keys=True, separators=(",", ":"), ) return hashlib.sha256(canonical.encode("utf-8")).hexdigest() def build_public_mcp_federation_receipt( *, runtime_version: str, observed_at: str | None = None, ) -> dict[str, Any]: """Build two product-scoped, aggregate-only MCP/RAG runtime receipts. This function performs no network call, database read/write, tool call, or RAG write. Internal endpoint URLs and raw tool registries are deliberately reduced to stable IDs and counts before reaching the public response. """ timestamp = observed_at or datetime.now(TAIPEI_TZ).isoformat(timespec="seconds") mcp = _safe_mcp_summary(_mcp_runtime_snapshot()) rag = _safe_rag_summary(_rag_runtime_snapshot()) pixelrag = _safe_pixelrag_summary(_pixelrag_snapshot()) blockers: list[str] = [] if not mcp["enabled"]: blockers.append("mcp_router_runtime_not_enabled") if mcp["server_count"] == 0 or mcp["tool_count"] == 0: blockers.append("mcp_runtime_inventory_empty") if not rag["enabled"]: blockers.append("rag_runtime_not_enabled") if not rag["embedding_signature"]: blockers.append("rag_embedding_signature_missing") if rag["embedding_version_state"] == "floating_tag_detected": blockers.append("rag_embedding_model_not_immutable") if not pixelrag["enabled"]: blockers.append("pixelrag_runtime_not_enabled") blockers = sorted(blockers) normalized_runtime = { "mcp": mcp, "rag": rag, "pixelrag": pixelrag, } receipts: list[dict[str, Any]] = [] for product in _FEDERATED_PRODUCTS: receipt: dict[str, Any] = { "receipt_schema_version": PUBLIC_FEDERATION_SCHEMA_VERSION, "product_id": product["product_id"], "canonical_repo": product["canonical_repo"], "runtime_role": product["runtime_role"], "runtime_version": str(runtime_version or "unknown"), "health_status": "ready" if not blockers else "partial_degraded", "runtime": deepcopy(normalized_runtime), "data_boundaries": { "scope": "aggregate_runtime_metadata_only", "pixelrag": "public_visual_receipts_no_formal_product_write", "rag": "pgvector_internal_only_no_public_content", "mcp": "server_ids_and_counts_only_no_endpoint_or_payload", }, "operation_boundaries": _public_operation_boundaries(), "blockers": list(blockers), } fingerprint = compute_public_federation_receipt_fingerprint(receipt) receipt["observed_at"] = timestamp receipt["receipt_id"] = ( f"mcp-federation:{product['product_id']}:{fingerprint[:16]}" ) receipt["integrity"] = { "algorithm": "sha256", "canonicalization": "json_sort_keys_compact_v1", "excluded_fields": ["receipt_id", "observed_at", "integrity"], "normalized_fingerprint_sha256": fingerprint, } receipts.append(receipt) return { "success": True, "schema_version": PUBLIC_FEDERATION_SCHEMA_VERSION, "policy": PUBLIC_FEDERATION_POLICY, "generated_at": timestamp, "status": "ready" if not blockers else "partial_degraded", "receipt_count": len(receipts), "receipts": receipts, "blockers": blockers, "operation_boundaries": _public_operation_boundaries(), "next_machine_action": ( "pin_embedding_model_and_verify_runtime_receipts" if blockers else "continue_scheduled_read_only_federation" ), } def _status_counts(items: list[dict[str, Any]]) -> dict[str, int]: counts: dict[str, int] = {} for item in items: status = str(item.get("status") or "unknown") counts[status] = counts.get(status, 0) + 1 return counts def _mcp_runtime_snapshot() -> dict[str, Any]: try: from services.mcp_router import MCP_BASE_HOSTS, TOOL_REGISTRY, is_mcp_router_enabled return { "enabled": is_mcp_router_enabled(), "servers": deepcopy(MCP_BASE_HOSTS), "caller_count": len(TOOL_REGISTRY), "tool_registry": { caller: { server: list(tools) for server, tools in servers.items() } for caller, servers in TOOL_REGISTRY.items() }, } except Exception as exc: return { "enabled": False, "servers": {}, "caller_count": 0, "tool_registry": {}, "error": str(exc)[:300], } def _rag_runtime_snapshot() -> dict[str, Any]: try: from services.rag_service import ( RAG_DEFAULT_THRESHOLD, RAG_DEFAULT_TOP_K, RAG_EMBED_DIM, RAG_EMBED_MODEL, get_embedding_signature, is_rag_enabled, ) return { "enabled": is_rag_enabled(), "vector_store": "pgvector", "embedding_model": RAG_EMBED_MODEL, "embedding_dim": RAG_EMBED_DIM, "embedding_signature": get_embedding_signature(), "default_top_k": RAG_DEFAULT_TOP_K, "default_threshold": RAG_DEFAULT_THRESHOLD, } except Exception as exc: return { "enabled": False, "vector_store": "pgvector", "embedding_model": "", "embedding_dim": 0, "embedding_signature": "", "error": str(exc)[:300], } def _pixelrag_snapshot() -> dict[str, Any]: try: from services.pixelrag_crawler_integration_service import ECOMMERCE_PLATFORM_PROFILES platforms = sorted( platform for platform in ECOMMERCE_PLATFORM_PROFILES if platform not in {"market_intel", "external_market"} ) return { "enabled": True, "platform_count": len(platforms), "platforms": platforms, "visual_rag_stage": "phase1_visual_evidence_receipts", } except Exception as exc: return { "enabled": False, "platform_count": 0, "platforms": [], "visual_rag_stage": "unavailable", "error": str(exc)[:300], } def _capability_inventory() -> list[dict[str, Any]]: return [ { "id": "mcp.omnisearch.tavily_exa", "family": "external_mcp", "external_capability": "Tavily / Exa style public web search through omnisearch MCP", "internal_plane": "mcp_router", "internal_entrypoint": "services.mcp_router.TOOL_REGISTRY[mcp_collector][omnisearch]", "status": "integrated_self_hosted_gateway", "writes": ["mcp_calls_log_async"], "data_boundary": "public_search_summary_only", "next_machine_action": "keep_mcp_router_health_and_cache_readback", }, { "id": "mcp.firecrawl.scrape", "family": "external_mcp", "external_capability": "Firecrawl style public page scrape", "internal_plane": "mcp_router", "internal_entrypoint": "services.mcp_router.TOOL_REGISTRY[*][firecrawl].scrape_url", "status": "integrated_self_hosted_gateway", "writes": ["mcp_calls_log_async"], "data_boundary": "approved_public_url_only", "next_machine_action": "enforce_source_contract_before_scheduler_attach", }, { "id": "mcp.postgres.query", "family": "internal_mcp", "external_capability": "SQL read interface exposed as MCP tool", "internal_plane": "mcp_router", "internal_entrypoint": "postgres.query for approved callers", "status": "integrated_read_only_contract", "writes": ["mcp_calls_log_async"], "data_boundary": "read_only_query_allowlist", "next_machine_action": "keep_disallowing_unknown_callers_and_write_tools", }, { "id": "mcp.filesystem.readonly", "family": "internal_mcp", "external_capability": "Filesystem MCP read diagnostics", "internal_plane": "mcp_router", "internal_entrypoint": "ops_diagnostics filesystem read-only tools", "status": "integrated_read_only_contract", "writes": ["mcp_calls_log_async"], "data_boundary": "allowed_directories_read_only", "next_machine_action": "keep_write_file_and_mutation_tools_rejected", }, { "id": "rag.pixelrag.visual_evidence", "family": "external_rag", "external_capability": "PixelRAG page screenshot and tile retrieval pattern", "internal_plane": "pixelrag_visual_evidence + internal RAG candidate lane", "internal_entrypoint": "services.pixelrag_crawler_integration_service", "status": "integrated_phase1_visual_receipts", "writes": ["artifact_file_only"], "data_boundary": "public_page_screenshot_tiles_no_price_write", "next_machine_action": "add_ocr_vlm_replay_before_promoting_to_pgvector_rag", }, { "id": "rag.pgvector.bge_m3", "family": "internal_rag", "external_capability": "General text RAG retrieval pattern", "internal_plane": "rag_service", "internal_entrypoint": "services.rag_service.RAGService.query", "status": "internal_primary_ready", "writes": ["rag_query_log_async"], "data_boundary": "ai_insights_pgvector_embedding_signature_guard", "next_machine_action": "keep_embedding_signature_and_feedback_guardrails", }, { "id": "rag.qwen3_vl_embedding", "family": "external_rag", "external_capability": "Multimodal visual embedding model for tile retrieval", "internal_plane": "ollama_first_visual_embedding_benchmark", "internal_entrypoint": "not_enabled_in_production", "status": "deferred_until_ollama_first_verified", "writes": [], "data_boundary": "no_hosted_visual_embedding_api", "next_machine_action": "benchmark_local_multimodal_embedding_then_design_pgvector_metadata", }, { "id": "rag.faiss_visual_index", "family": "external_rag", "external_capability": "FAISS visual retrieval index used by some PixelRAG pipelines", "internal_plane": "pgvector_first_policy", "internal_entrypoint": "not_enabled_in_production", "status": "rejected_for_production_without_adr", "writes": [], "data_boundary": "pgvector_is_the_only_production_vector_store", "next_machine_action": "use_pgvector_compatible_metadata_or_write_adr_before_any_faiss_trial", }, { "id": "mcp.gemini_grounding", "family": "external_mcp", "external_capability": "Gemini grounding as hosted external search fallback", "internal_plane": "mcp_collector_final_fallback", "internal_entrypoint": "services.mcp_collector_service guarded fallback", "status": "disabled_by_default_fallback_only", "writes": ["mcp_cache_only_when_explicitly_enabled"], "data_boundary": "gemini_api_hard_disabled_by_default", "next_machine_action": "prefer_self_hosted_mcp_or_ollama_static_fallback", }, ] def build_external_mcp_rag_integration_readback( *, target_family: str | None = None, ) -> dict[str, Any]: """Describe how external MCP/RAG capabilities are absorbed internally.""" family_filter = str(target_family or "").strip().lower() inventory = _capability_inventory() if family_filter: inventory = [ item for item in inventory if str(item.get("family") or "").lower() == family_filter ] counts = _status_counts(inventory) unresolved = [ item for item in inventory if str(item.get("status") or "").startswith(("deferred", "rejected", "disabled")) ] absorbed = [ item for item in inventory if item not in unresolved ] all_absorbed = len(unresolved) == 0 return { "success": True, "policy": POLICY, "generated_at": datetime.now(timezone.utc).isoformat(), "status": "partially_integrated" if not all_absorbed else "fully_integrated", "answer_to_owner": ( "不是全部完成;已把主要外部 MCP/RAG 放進內部可治理 registry," "其中 self-hosted MCP、pgvector RAG、PixelRAG phase1 已整合," "多模態 embedding / FAISS / Gemini grounding 仍需條件或維持停用。" if not all_absorbed else "目前 registry 內的外部 MCP/RAG 都已有內部治理落點。" ), "completion": { "total_capabilities": len(inventory), "absorbed_count": len(absorbed), "unresolved_count": len(unresolved), "all_absorbed": all_absorbed, "status_counts": counts, }, "runtime": { "mcp": _mcp_runtime_snapshot(), "rag": _rag_runtime_snapshot(), "pixelrag": _pixelrag_snapshot(), "env_flags": { "MCP_ROUTER_ENABLED": _enabled(os.getenv("MCP_ROUTER_ENABLED")), "RAG_ENABLED": _enabled(os.getenv("RAG_ENABLED")), "GEMINI_API_HARD_DISABLED": _enabled(os.getenv("GEMINI_API_HARD_DISABLED", "true")), }, }, "inventory": inventory, "next_machine_actions": [ { "priority": "P0", "action": "wire_pixelrag_receipts_to_internal_rag_candidate_replay", "status": "ready_after_ocr_vlm_replay_contract", }, { "priority": "P0", "action": "add_mcp_router_health_readback_to_ai_automation_smoke", "status": "ready", }, { "priority": "P1", "action": "benchmark_ollama_first_visual_embedding", "status": "blocked_until_model_runtime_verified", }, { "priority": "P1", "action": "promote_successful_marketplace_visual_receipts_to_source_contracts", "status": "ready_for_shopee_warning_for_coupang", }, ], "controlled_apply": _controlled_apply_boundary(), } __all__ = [ "POLICY", "PUBLIC_FEDERATION_POLICY", "PUBLIC_FEDERATION_SCHEMA_VERSION", "build_external_mcp_rag_integration_readback", "build_public_mcp_federation_receipt", "compute_public_federation_receipt_fingerprint", ]