112 lines
3.1 KiB
Python
112 lines
3.1 KiB
Python
"""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)
|
|
|