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)

IDDescription
notifications.showShow toast notifications
statusbar.setUpdate the status bar

Normal Capabilities (prompted at install)

IDDescription
fs.readRead files (scoped by glob patterns)
fs.writeWrite files (scoped by glob patterns)
fs.watchWatch file changes
fs.deleteDelete files
net.fetchMake HTTP requests (scoped by URL patterns)
clipboard.readRead the clipboard
clipboard.writeWrite to the clipboard
workspace.readRead workspace state (open files, active editor)
workspace.writeModify workspace state (open/edit files)
secrets.readRead from the OS keychain
secrets.writeWrite to the OS keychain
events.publishPublish cross-extension events
events.subscribeSubscribe to cross-extension events

Sensitive Capabilities (extra warning)

IDDescription
commands.executeHostExecute host-registered commands

Verified-Only Capabilities

These require a verified publisher (domain proof or GitHub OAuth):

IDDescription
terminal.spawnSpawn terminal processes
terminal.shellRun shell commands (pipes, redirects)
process.killKill running processes

Declaring Permissions

In oxp.json, each permission entry has three fields:

json
{
  "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 PermissionWIT Import Unlocked
fs.readoxp:host/fs.read-file, oxp:host/fs.stat, oxp:host/fs.list-dir
fs.writeoxp:host/fs.write-file
net.fetchoxp:host/net.fetch (URL filtered)
secrets.readoxp: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.