Capability System
Capability declarations, plugin permissions, action-aware tool enforcement, and the runtime capability ledger.
Aleph separates three questions:
- What a plugin or extension registers.
- What resources a plugin declares that it needs.
- What the running agent is allowed to execute now.
src/extension/capability.rs answers the first question. Plugin manifest permissions and the shared scoped-tool, approval, and sandbox layers answer the other two.
Capability declarations
The production declaration enum is intentionally small:
pub enum CapabilityDeclaration {
Tool(ToolRegistration),
Hook(HookRegistration),
Service(ServiceRegistration),
Skill(SkillRegistration),
Agent(AgentRegistration),
McpServer(McpServerConfig),
}Each declaration is owned by a plugin or, for an MCP server configuration, by the runtime that supplies it. The registrar validates ownership and dispatches it to PluginRegistry or the MCP path.
| Variant | Registration target | Tier |
|---|---|---|
Tool | Callable tool registry | Core |
Hook | Hook executor | Core |
Skill | Plugin skill registry and shared SkillSystem | Core |
Agent | Agent registry | Important |
Service | Service manager | Pluggable |
McpServer | MCP manager integration | Pluggable |
Plugin commands/ Markdown is represented as a command-type skill registration. There are no separate channel, provider, HTTP-route, CLI, or gateway-method variants in the current declaration model.
A CapabilitySource records the plugin ID, discovery origin, and manifest format. Supported source formats include Claude Code, Aleph TOML, Codex, Cursor, auto-discovery, and runtime registration.
Plugin permissions
The Aleph extension manifest declares resource requirements under its permission section:
[aleph.permissions]
network = true
filesystem = "read"
env = true
shell = false
background = falseThe permission vocabulary is:
networkfilesystem:read,filesystem:write, or full filesystem accessenvshellbackground
A [[aleph.services]] declaration requires background = true. WASM-specific declarations can further constrain workspace prefixes, HTTP endpoints, credentials, rate limits, tool invocation, and secret injection.
These are declarations and host-registration gates. They do not grant an agent an unconditional execution right. Calls still pass through the scoped tool service, tool metadata, approval policy, execution tier, and sandbox command policy.
Tool enforcement
Tool policy is action-aware and uses the tool's declared metadata rather than guessing from a name. The effective permission combines explicit tool rules, agent and channel policy, and the execution tier; the most restrictive applicable rule wins.
The user-facing execution tiers are:
| Tier | Behavior |
|---|---|
ask | Ask before mutating tool calls; unknown tools fail closed |
auto | Auto-allow idempotent tools; destructive operations still require approval |
full | Auto-allow except for the independent hard security floor |
[sandbox.command_policy] is that hard floor. No execution tier or plugin declaration can lower it. Action-aware approval binds a grant to the concrete command and its fingerprint rather than only to a tool name.
The operator gate is a separate boundary for self-management operations. For example, hub_install_run, skill management, and identity operations cannot be enabled by an ordinary chat-tier channel merely because a plugin declared a capability.
Runtime capability ledger
Runtime binaries such as node, uv, ffmpeg, or playwright-cli use a different ledger from extension capabilities:
~/.aleph/runtimes/ledger.jsonCapabilityLedger is the persisted source of truth for whether Aleph can use a runtime executable. It does not download or install anything itself. The probe and bootstrap modules perform those operations, then update the ledger.
A ledger entry records:
- capability name
- executable path
- detected version
- last successful probe time
- source:
systemoraleph_managed - status:
missing,probing,bootstrapping,ready, orstale
The runtime install flow is:
load ledger
→ probe PATH and Aleph-managed paths
→ resolve dependencies
→ bootstrap when a supported install spec exists
→ verify the resulting binary
→ write Ready state atomicallyruntimes.list reads the ledger and runtime specifications. runtimes.refresh probes known capabilities. runtimes.install accepts a capability name, runs asynchronously, and publishes progress events; the final state is persisted in the same ledger.json. A missing or corrupt ledger is recreated rather than trusted.
This runtime ledger is not the Hub catalog, not the Hub trust disclosure, and not a per-plugin capability claim. Hub entries carry their own InstallSpec, trust tier, version, and optional SHA-256 pin in hub_catalog.db.
Security boundaries
- Manifest declarations are validated before registration.
- Capability ownership prevents one plugin from registering another plugin's component.
- Plugin and skill content is scanned for injection and dangerous patterns before untrusted installation.
- Secrets use the encrypted vault and runtime injection boundary.
- Tool execution is enforced at a shared scoped-tool choke point.
- Runtime installation is serialized per capability and records only verified executable state.
Code locations
src/extension/capability.rs— declaration enum, tiers, and source metadatasrc/extension/registrar/— declaration validation and registrationsrc/extension/registry/— plugin registrationssrc/extension/manifest/— permission parsingsrc/tools/scoped/— tool policy enforcementsrc/config/types/policies/exec_tier.rs— execution-tier compositionsrc/sandbox/command_policy/— hard command floorsrc/runtimes/ledger.rs— persisted runtime ledgersrc/runtimes/ensure.rs— probe, bootstrap, and ledger update orchestrationsrc/gateway/handlers/runtimes.rs— runtime list, refresh, and install RPCs
Related pages
- Extensions — Plugin capabilities and runtimes
- Extension System — registration flow
- Extensions Store — trust-gated extension installation
- Security Overview — execution and approval boundaries