"""Canonical, declarative Capability Registry v1 for Emma.""" from dataclasses import dataclass from enum import Enum from types import MappingProxyType from typing import Mapping, Tuple class RiskLevel(str, Enum): READ = "read" WRITE = "write" HIGH_IMPACT = "high_impact" FORBIDDEN = "forbidden" class Availability(str, Enum): ACTIVE = "active" PLANNED = "planned" FORBIDDEN = "forbidden" @dataclass(frozen=True) class Capability: id: str display_name: str description: str category: str risk_level: RiskLevel availability: Availability execution_owner: str backend_tool: str | None required_actor_scope: Tuple[str, ...] input_schema: Mapping[str, str] output_schema: Mapping[str, str] approval_required: bool approval_binding: str | None audit_required: bool rollback_required: bool self_approval_forbidden: bool allowed_targets: Tuple[str, ...] external_source_policy: str | None _EMPTY_SCHEMA: Mapping[str, str] = MappingProxyType({}) def _capability( capability_id: str, display_name: str, description: str, category: str, risk_level: RiskLevel, availability: Availability, execution_owner: str, backend_tool: str | None, required_actor_scope: Tuple[str, ...], approval_required: bool, approval_binding: str | None, audit_required: bool, rollback_required: bool, self_approval_forbidden: bool, allowed_targets: Tuple[str, ...], external_source_policy: str | None, ) -> Capability: return Capability( id=capability_id, display_name=display_name, description=description, category=category, risk_level=risk_level, availability=availability, execution_owner=execution_owner, backend_tool=backend_tool, required_actor_scope=required_actor_scope, input_schema=_EMPTY_SCHEMA, output_schema=_EMPTY_SCHEMA, approval_required=approval_required, approval_binding=approval_binding, audit_required=audit_required, rollback_required=rollback_required, self_approval_forbidden=self_approval_forbidden, allowed_targets=allowed_targets, external_source_policy=external_source_policy, ) _CAPABILITIES_TUPLE: Tuple[Capability, ...] = ( _capability( "emma.chat", "Emma chat", "Conversational reasoning through Emma.", "conversation", RiskLevel.READ, Availability.ACTIVE, "opax-mcp", "run_emma", ("authenticated_user",), False, None, True, False, False, ("opax.vauco.no",), "none", ), _capability( "emma.analyze_user_text", "Analyze user-provided text", "Analyze, summarize, and structure text provided in the current request.", "conversation", RiskLevel.READ, Availability.ACTIVE, "opax-mcp", "run_emma", ("authenticated_user",), False, None, True, False, False, ("user_provided_text",), "user_provided_only", ), _capability( "vauco.context.retrieve", "Retrieve approved VAUCO context", "Retrieve approved VAUCO internal context.", "context", RiskLevel.READ, Availability.PLANNED, "opax-mcp", None, ("authenticated_user", "vauco_context_read"), False, None, True, False, False, ("approved_vauco_sources",), "approved_internal_only", ), _capability( "conversation.session_history", "Retrieve active session history", "Retrieve bounded history for the active user session.", "context", RiskLevel.READ, Availability.PLANNED, "opax-web", None, ("authenticated_user", "conversation_read"), False, None, True, False, False, ("active_user_session",), "session_scoped", ), _capability( "memory.morphic.read", "Read scoped Morphic memory", "Read actor-scoped Morphic memory.", "memory", RiskLevel.READ, Availability.PLANNED, "opax-mcp", None, ("authenticated_user", "morphic_memory_read"), False, None, True, False, False, ("actor_scoped_memory",), "actor_scoped", ), _capability( "gitea.read_commits", "Read Gitea commits", "Read commit history from the authoritative Gitea service.", "gitea", RiskLevel.READ, Availability.PLANNED, "opax-mcp", "list_commits", ("authenticated_user", "gitea_read"), False, None, True, False, False, ("git.vauco.no",), "internal_authoritative_only", ), _capability( "gitea.read_file", "Read Gitea file", "Read a file from the authoritative Gitea service.", "gitea", RiskLevel.READ, Availability.PLANNED, "opax-mcp", "get_file", ("authenticated_user", "gitea_read"), False, None, True, False, False, ("git.vauco.no",), "internal_authoritative_only", ), _capability( "gitea.list_repo_files", "List Gitea repo files", "List files in a directory from the authoritative Gitea service.", "gitea", RiskLevel.READ, Availability.PLANNED, "opax-mcp", "list_repo_files", ("authenticated_user", "gitea_read"), False, None, True, False, False, ("git.vauco.no",), "internal_authoritative_only", ), _capability( "gitea.fetch_normalized_source_meta", "Fetch Normalized Source Metadata", "Resolves a Git ref, fetches the source archive, normalizes it, and returns deterministic build metadata.", "gitea", RiskLevel.READ, Availability.PLANNED, "opax-mcp", "fetch_and_normalize_source", ("authenticated_user", "gitea_read"), False, None, True, False, False, ("git.vauco.no",), "internal_authoritative_only", ), _capability( "cloudbuild.read_status", "Read Cloud Build status", "Read Cloud Build status in the approved VAUCO project.", "cloudbuild", RiskLevel.READ, Availability.PLANNED, "opax-mcp", None, ("authenticated_user", "cloudbuild_read"), False, None, True, False, False, ("propane-will-491900-m5",), "internal_project_only", ), _capability( "cloudrun.read_status", "Read Cloud Run status", "Read Cloud Run status in the approved VAUCO project.", "cloudrun", RiskLevel.READ, Availability.PLANNED, "opax-mcp", None, ("authenticated_user", "cloudrun_read"), False, None, True, False, False, ("propane-will-491900-m5", "us-central1"), "internal_project_only", ), _capability( "github.intake.read", "Read reviewed external GitHub repository", "Read an explicitly requested external repository in read-only quarantine.", "github_intake", RiskLevel.READ, Availability.PLANNED, "opax-mcp", None, ("authenticated_user", "github_intake_read"), False, None, True, False, False, ("explicitly_requested_repository",), "explicit_read_only_quarantine", ), _capability( "gitea.create_issue", "Create Gitea issue", "Create an approved Gitea issue.", "gitea", RiskLevel.WRITE, Availability.PLANNED, "opax-mcp", "create_issue", ("authenticated_user", "gitea_write"), True, "exact_repository_title_body", True, False, True, ("git.vauco.no",), "internal_authoritative_only", ), _capability( "gitea.push_change", "Push approved Gitea change", "Push an approved change to Gitea.", "gitea", RiskLevel.WRITE, Availability.PLANNED, "opax-mcp", "push_file", ("authenticated_user", "gitea_write"), True, "exact_repository_branch_path_content_sha", True, True, True, ("git.vauco.no",), "internal_authoritative_only", ), _capability( "cloudbuild.trigger", "Trigger approved Cloud Build", "Trigger an approved Cloud Build.", "cloudbuild", RiskLevel.HIGH_IMPACT, Availability.PLANNED, "opax-mcp", "trigger_build", ("authenticated_user", "cloudbuild_execute"), True, "exact_build_source_config_substitutions", True, False, True, ("propane-will-491900-m5",), "internal_project_only", ), _capability( "cloudrun.deploy_digest", "Deploy approved Cloud Run image digest", "Deploy an approved immutable image digest to Cloud Run.", "cloudrun", RiskLevel.HIGH_IMPACT, Availability.PLANNED, "opax-mcp", "build_and_deploy_service", ("authenticated_user", "cloudrun_deploy"), True, "exact_service_region_image_digest_rollback_revision", True, True, True, ("propane-will-491900-m5", "us-central1"), "internal_project_only", ), _capability( "emma.update_ui", "Update Emma UI", "Update Emma UI through the approved self-update flow.", "self_update", RiskLevel.HIGH_IMPACT, Availability.PLANNED, "opax-mcp", None, ("authenticated_user", "emma_self_update"), True, "exact_repository_branch_diff_tests_image_digest_service", True, True, True, ("git.vauco.no", "opax.vauco.no"), "internal_authoritative_only", ), _capability( "emma.update_backend", "Update Emma backend", "Update Emma backend through the approved self-update flow.", "self_update", RiskLevel.HIGH_IMPACT, Availability.PLANNED, "opax-mcp", None, ("authenticated_user", "emma_self_update"), True, "exact_repository_branch_diff_tests_image_digest_service", True, True, True, ("git.vauco.no", "opax-mcp"), "internal_authoritative_only", ), _capability( "emma.update_model_config", "Update Emma model configuration", "Update model configuration through the approved self-update flow.", "self_update", RiskLevel.HIGH_IMPACT, Availability.PLANNED, "opax-mcp", None, ("authenticated_user", "emma_self_update"), True, "exact_model_config_diff_tests_target", True, True, True, ("opax-mcp", "os-vauco-agent"), "internal_project_only", ), _capability( "emma.cli", "Emma CLI", "Use Emma through a CLI governed by the same policy as the UI.", "interface", RiskLevel.READ, Availability.PLANNED, "opax-mcp", None, ("authenticated_user",), False, None, True, False, False, ("approved_vauco_operator_environment",), "same_policy_as_emma_ui", ), _capability( "terminal.arbitrary_shell", "Arbitrary terminal shell", "Arbitrary terminal execution is prohibited.", "terminal", RiskLevel.FORBIDDEN, Availability.FORBIDDEN, "none", None, (), False, None, True, False, True, (), "prohibited", ), ) CAPABILITIES: Mapping[str, Capability] = MappingProxyType( {capability.id: capability for capability in _CAPABILITIES_TUPLE} ) def get_capability(capability_id: str) -> Capability | None: return CAPABILITIES.get(capability_id) def list_capabilities() -> Tuple[Capability, ...]: return _CAPABILITIES_TUPLE def list_active_capabilities() -> Tuple[Capability, ...]: return tuple( capability for capability in _CAPABILITIES_TUPLE if capability.availability == Availability.ACTIVE )