Permissions
Declare permissions in timon.permissions. Request only the capabilities your extension uses. Missing capabilities fail rather than returning fabricated data.
| Permission | Surface |
|---|---|
missions:spawn, missions:read | Start missions; read caller-scoped missions |
kanban:write, kanban:read | Create/update tasks; read caller-scoped tasks |
notify | Reports and alerts |
storage | Plugin-scoped key/value storage and data directory |
settings | Declared plugin settings |
secrets:read | Authorised vault secret lookup |
users:read | Explicit checks for user-protected functionality |
http:outbound | Outbound ctx.fetch |
host:exec | Host command execution |
events:subscribe | Permitted daemon event subscriptions |
usage:read, usage:collect | Read usage; register usage probes |
backends:register | Register backend profiles or dialects |
events:register, events:publish | Register and publish business events |
workflows:triggers:register, workflows:executors:register | Workflow extension callbacks |
transports:register | Messaging transport registration |
connections:read, connections:write | Integration connections |
realtime:publish | Signal your browser half that data changed, to its owner account only (Live updates) |
The integration families require API 3; realtime:publish requires API 4. See the generated SDK reference for exact method shapes.
missions:spawn, host:exec and http:outbound are denied by default even when declared. The operator must configure pluginPolicy in timon.config.json.
{
"pluginPolicy": {
"spawn": {"approved": ["acme-weather"], "max": 5, "windowMs": 3600000},
"exec": {"allow": ["rsync"]},
"http": {"allow": ["api.example.com", "*.example.com"]}
}
}
The spawn approval names the plugin; limits apply per time window. An HTTP wildcard covers subdomains, not the apex. Empty allowlists refuse access.
Backend CLIs, daemon CLIs, credential helpers and generic launchers cannot be opened through this allowlist. The check is not an inspection of executable contents or all argument semantics: allowlisting a tool still requires trust. Catch policy errors and show the rule to the user instead of retrying indefinitely.
The host plugin loads once. Call ctx.user() inside the route handler to read the current caller; never cache a user at plugin activation.
Inside a plugin route, mission and task operations are scoped to that caller. Outside a request, ctx.user() is undefined, and reads are limited to rows owned by plugin:<id>. A background job does not inherit an administrator's identity.
ctx.assertPermission(permission) checks a declared capability when applicable and the caller's rights. User permissions are denied when there is no user. Declared UI surfaces also have server-side permission targets: a hidden plugin route can return 404, not 403. Do not treat a client-side visibility check as authorization.