Fundamentals
Permissions
The capability catalog, sensitivity tiers, and how permissions protect users.
OXP's permission system is built on the principle of least privilege. Extensions declare what they need in the manifest, users consent at install time, and the capability broker enforces grants at runtime. An extension literally cannot call APIs it wasn't granted — the WIT import is simply not linked.
The Capability Catalog
Every permission has an id from this catalog, a sensitivity tier, and a description shown at install.
Ambient Capabilities (always granted)
| ID | Description |
|---|---|
notifications.show | Show toast notifications |
statusbar.set | Update the status bar |
Normal Capabilities (prompted at install)
| ID | Description |
|---|---|
fs.read | Read files (scoped by glob patterns) |
fs.write | Write files (scoped by glob patterns) |
fs.watch | Watch file changes |
fs.delete | Delete files |
net.fetch | Make HTTP requests (scoped by URL patterns) |
clipboard.read | Read the clipboard |
clipboard.write | Write to the clipboard |
workspace.read | Read workspace state (open files, active editor) |
workspace.write | Modify workspace state (open/edit files) |
secrets.read | Read from the OS keychain |
secrets.write | Write to the OS keychain |
events.publish | Publish cross-extension events |
events.subscribe | Subscribe to cross-extension events |
Sensitive Capabilities (extra warning)
| ID | Description |
|---|---|
commands.executeHost | Execute host-registered commands |
Verified-Only Capabilities
These require a verified publisher (domain proof or GitHub OAuth):
| ID | Description |
|---|---|
terminal.spawn | Spawn terminal processes |
terminal.shell | Run shell commands (pipes, redirects) |
process.kill | Kill running processes |
Declaring Permissions
In oxp.json, each permission entry has three fields:
{
"permissions": [
{
"id": "fs.read",
"scope": ["/workspace/**"],
"rationale": "Read source files for analysis"
},
{
"id": "net.fetch",
"scope": ["https://api.github.com/*"],
"rationale": "Fetch repository metadata from GitHub"
}
]
}- **
id** — capability name from the catalog above - **
scope** — glob patterns restricting what the capability can access - **
rationale** — plain-text explanation shown to the user
Install-Time Prompts
When a user runs oxp install, they see each requested permission with its rationale. They choose:
- Allow All — grant every requested permission
- Customize — grant/deny individual permissions
- Deny — cancel installation
Choices are persisted per (publisher, slug) in grants.json. On version updates, if new permissions appear, the user is re-prompted for just the new ones.
How Permissions Map to WIT Imports
For component-v1 extensions, permissions directly control which WIT interfaces are linked:
| Manifest Permission | WIT Import Unlocked |
|---|---|
fs.read | oxp:host/fs.read-file, oxp:host/fs.stat, oxp:host/fs.list-dir |
fs.write | oxp:host/fs.write-file |
net.fetch | oxp:host/net.fetch (URL filtered) |
secrets.read | oxp:host/secrets.get |
| (always) | oxp:host/storage, oxp:host/log, oxp:host/ui |
The registry validates that manifest.permissions ⊇ component.imports on upload. A mismatch is a publish error. The binary cannot fabricate symbols it did not declare.