Permission System Design
- Author: @Mossaka
- Date: 2025-07-11
Overview
The permission system provides fine-grained, per-component capability controls in the Wassette MCP server. This document describes the architecture,implementation, and future development plans.
Architecture Overview
Core Components
graph TB
Client[MCP Client] --> Server[Wassette MCP Server]
Server --> LM[LifecycleManager]
LM --> PR[PolicyRegistry]
LM --> CR[ComponentRegistry]
LM --> Engine[Wasmtime Engine]
LM --> Resources[Resources]
PR --> Permissions[Permissions]
subgraph "Resources"
PolicyFile[Component Policy Files]
ComponentFile[Component.wasm]
end
subgraph "Permissions"
Network[Network Permissions]
Storage[Storage Permissions]
Environment[Environment Permissions]
end
Key Design Principles
- Per-Component Policies: Each component has its own permission policy, co-located with the component binary under the
plugin_dir
directory - Principle of Least Privilege: Components only get permissions they need
- Dynamic Control: Permissions can be granted at runtime using the
grant-permission
tool
Current Implementation Status
1. Per-Component Policy System
Status: ✅ Implemented
Each component can have its own policy file stored as {component_id}.policy.yaml
co-located with the component binary.
#![allow(unused)] fn main() { // Current Implementation struct PolicyRegistry { component_policies: HashMap<String, Arc<WasiStateTemplate>>, } impl LifecycleManager { async fn get_wasi_state_for_component(&self, component_id: &str) -> Result<WasiState> { // Returns component-specific WASI state or default restrictive policy } } }
2. Policy Lifecycle Management
Status: ✅ Implemented
Built-in tools for managing component policies:
attach-policy
: Attach policy from file:// or https:// URIdetach-policy
: Remove policy from componentget-policy
: Get policy information for component
3. Granular Permission System
Status: ✅ Implemented
The grant_storage_permission
method allows atomic permission grants:
#![allow(unused)] fn main() { pub async fn grant_storage_permission( &self, component_id: &str, details: &serde_json::Value, ) -> Result<()> }
The grant_network_permission
method allows atomic permission grants:
#![allow(unused)] fn main() { pub async fn grant_network_permission( &self, component_id: &str, details: &serde_json::Value, ) -> Result<()> }
Supported permission types:
- Network:
{"host": "api.example.com"}
- Storage:
{"uri": "fs:///path", "access": ["read", "write"]}
4. Policy Persistence
Status: ✅ Implemented
- Policies are stored co-located with components
- Policy associations are restored on server restart
- Metadata tracking for policy sources
Built-in Tools
get-policy
: Get policy informationgrant-storage-permission
: Grant storage accessgrant-network-permission
: Grant network accessgrant-environment-variable-permission
: Grant environment variable accessrevoke-storage-permission
: Revoke storage access permissionsrevoke-network-permission
: Revoke network access permissionsrevoke-environment-variable-permission
: Revoke environment variable access permissionsreset-permission
: Reset all permissions for a componentload-component
: Load WebAssembly componentunload-component
: Unload componentlist-components
: List loaded componentssearch-components
: Search available components from registry
Permission Types and Structure
Policy File Format
version: "1.0"
description: "Component-specific security policy"
permissions:
network:
allow:
- host: "api.example.com"
- host: "cdn.example.com"
environment:
allow:
- key: "API_KEY"
- key: "CONFIG_URL"
storage:
allow:
- uri: "fs:///tmp/workspace"
access: ["read", "write"]
- uri: "fs:///var/cache"
access: ["read"]
Future Development Roadmap
- Policy Signing: Verify policy integrity with signatures
- Policy Checksums: Verify downloaded policy integrity
- Policy Caching: Optimize policy loading and parsing