OSVauco/opax-mcp/capability_registry.py

254 lines
10 KiB
Python

"""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(
"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
)