"""Canonical capability registry for command/task/gateway scope policy.""" from __future__ import annotations from dataclasses import dataclass @dataclass(frozen=True, slots=True) class CapabilityScope: key: str label: str description: str group: str configurable: bool = True owner_path: str = "/settings/security/permissions/" GLOBAL_SCOPE_KEY = "global.override" CAPABILITY_SCOPES: tuple[CapabilityScope, ...] = ( CapabilityScope( key="gateway.contacts", label="Gateway contacts command", description="Handles .contacts over gateway channels.", group="gateway", ), CapabilityScope( key="gateway.help", label="Gateway help command", description="Handles .help over gateway channels.", group="gateway", ), CapabilityScope( key="gateway.whoami", label="Gateway whoami command", description="Handles .whoami over gateway channels.", group="gateway", ), CapabilityScope( key="gateway.tasks", label="Gateway .tasks commands", description="Handles .tasks list/show/complete/undo over gateway channels.", group="tasks", ), CapabilityScope( key="gateway.approval", label="Gateway approval commands", description="Handles .approval/.codex/.claude approve/deny over gateway channels.", group="command", ), CapabilityScope( key="tasks.submit", label="Task submissions from chat", description="Controls automatic task creation from inbound messages.", group="tasks", owner_path="/settings/tasks/", ), CapabilityScope( key="tasks.commands", label="Task command verbs (.task/.undo/.epic)", description="Controls explicit task command verbs.", group="tasks", owner_path="/settings/tasks/", ), CapabilityScope( key="command.bp", label="Business plan command", description="Controls Business Plan command execution.", group="command", owner_path="/settings/command-routing/", ), CapabilityScope( key="command.codex", label="Codex command", description="Controls Codex command execution.", group="agentic", owner_path="/settings/command-routing/", ), CapabilityScope( key="command.claude", label="Claude command", description="Controls Claude command execution.", group="agentic", owner_path="/settings/command-routing/", ), ) SCOPE_BY_KEY = {row.key: row for row in CAPABILITY_SCOPES} GROUP_LABELS: dict[str, str] = { "gateway": "Gateway", "tasks": "Tasks", "command": "Commands", "agentic": "Agentic", "other": "Other", } def all_scope_keys(*, configurable_only: bool = False) -> list[str]: rows = [ row.key for row in CAPABILITY_SCOPES if (not configurable_only or bool(row.configurable)) ] return rows def scope_record(scope_key: str) -> CapabilityScope | None: key = str(scope_key or "").strip().lower() return SCOPE_BY_KEY.get(key)