Skip to content

capabilities

capabilities

RBAC capability system — fine-grained permission model for tool dispatch.

Classes

Capability

Bases: str, Enum

Fine-grained capability labels.

CapabilityGrant dataclass

CapabilityGrant(capability: str, pattern: str = '*')

A single capability grant for an agent.

AgentPolicy dataclass

AgentPolicy(
    agent_id: str,
    grants: List[CapabilityGrant] = list(),
    deny: List[str] = list(),
)

Policy for a specific agent.

CapabilityPolicy

CapabilityPolicy(
    *,
    policy_path: Optional[str] = None,
    default_deny: bool = True,
)

RBAC capability policy for tool dispatch.

Checks whether an agent has the required capability to invoke a tool. Policy can be loaded from a JSON file or configured programmatically.

Default policy: if no explicit policy exists for an agent, capabilities are denied. Callers must opt into a permissive policy explicitly.

Source code in src/diapason/security/capabilities.py
def __init__(
    self,
    *,
    policy_path: Optional[str] = None,
    default_deny: bool = True,
) -> None:
    self._policies: Dict[str, AgentPolicy] = {}
    self._default_deny = default_deny
    self._policy_path = Path(policy_path).expanduser() if policy_path else None

    self._rust_impl = None
    try:
        from diapason._rust_bridge import get_rust_module

        _rust = get_rust_module()
        self._rust_impl = _rust.CapabilityPolicy(default_deny=default_deny)
    except (ImportError, AttributeError, RuntimeError):
        self._rust_impl = None

    if self._policy_path:
        self._load_file(self._policy_path)
Attributes
default_deny property
default_deny: bool

Whether unmatched capability checks are denied.

has_explicit_policy property
has_explicit_policy: bool

Whether an administrator supplied a policy file.

Methods:
grant
grant(
    agent_id: str, capability: str, pattern: str = "*"
) -> None

Grant a capability to an agent.

Source code in src/diapason/security/capabilities.py
def grant(self, agent_id: str, capability: str, pattern: str = "*") -> None:
    """Grant a capability to an agent."""
    policy = self._policies.setdefault(
        agent_id,
        AgentPolicy(agent_id=agent_id),
    )
    policy.grants.append(CapabilityGrant(capability=capability, pattern=pattern))
    if self._rust_impl is not None:
        self._rust_impl.grant(agent_id, capability, pattern)
deny
deny(agent_id: str, capability: str) -> None

Explicitly deny a capability to an agent.

Source code in src/diapason/security/capabilities.py
def deny(self, agent_id: str, capability: str) -> None:
    """Explicitly deny a capability to an agent."""
    policy = self._policies.setdefault(
        agent_id,
        AgentPolicy(agent_id=agent_id),
    )
    policy.deny.append(capability)
    if self._rust_impl is not None:
        self._rust_impl.deny(agent_id, capability)
check
check(
    agent_id: str, capability: str, resource: str = ""
) -> bool

Check whether agent_id has capability for resource.

Returns True if allowed, False if denied.

Source code in src/diapason/security/capabilities.py
def check(self, agent_id: str, capability: str, resource: str = "") -> bool:
    """Check whether *agent_id* has *capability* for *resource*.

    Returns True if allowed, False if denied.
    """
    if self._rust_impl is not None:
        return self._rust_impl.check(agent_id, capability, resource)
    return self._check_python(agent_id, capability, resource)
list_grants
list_grants(agent_id: str) -> List[CapabilityGrant]

List all grants for an agent.

Source code in src/diapason/security/capabilities.py
def list_grants(self, agent_id: str) -> List[CapabilityGrant]:
    """List all grants for an agent."""
    policy = self._policies.get(agent_id)
    return list(policy.grants) if policy else []
list_agents
list_agents() -> List[str]

List all agents with explicit policies.

Source code in src/diapason/security/capabilities.py
def list_agents(self) -> List[str]:
    """List all agents with explicit policies."""
    return list(self._policies.keys())
save
save(path: Path) -> None

Atomically save policy to an owner-only JSON file.

Source code in src/diapason/security/capabilities.py
def save(self, path: Path) -> None:
    """Atomically save policy to an owner-only JSON file."""
    agents = []
    for agent_id, policy in self._policies.items():
        agents.append(
            {
                "agent_id": agent_id,
                "grants": [
                    {"capability": g.capability, "pattern": g.pattern}
                    for g in policy.grants
                ],
                "deny": policy.deny,
            }
        )
    path.parent.mkdir(mode=0o700, parents=True, exist_ok=True)
    payload = json.dumps({"agents": agents}, indent=2) + "\n"
    descriptor, temporary_name = tempfile.mkstemp(
        prefix=f".{path.name}.",
        dir=path.parent,
        text=True,
    )
    temporary_path = Path(temporary_name)
    try:
        restreindre_au_proprietaire(descriptor)
        with os.fdopen(descriptor, "w", encoding="utf-8") as handle:
            handle.write(payload)
            handle.flush()
            os.fsync(handle.fileno())
        temporary_path.replace(path)
        path.chmod(0o600)
    except BaseException:
        try:
            os.close(descriptor)
        except OSError:
            pass
        temporary_path.unlink(missing_ok=True)
        raise

Functions: