Skip to main content

Permissions

Declare permissions in timon.permissions. Request only the capabilities your extension uses. Missing capabilities fail rather than returning fabricated data.

PermissionSurface
missions:spawn, missions:readStart missions; read caller-scoped missions
kanban:write, kanban:readCreate/update tasks; read caller-scoped tasks
notifyReports and alerts
storagePlugin-scoped key/value storage and data directory
settingsDeclared plugin settings
secrets:readAuthorised vault secret lookup
users:readExplicit checks for user-protected functionality
http:outboundOutbound ctx.fetch
host:execHost command execution
events:subscribePermitted daemon event subscriptions
usage:read, usage:collectRead usage; register usage probes
backends:registerRegister backend profiles or dialects
events:register, events:publishRegister and publish business events
workflows:triggers:register, workflows:executors:registerWorkflow extension callbacks
transports:registerMessaging transport registration
connections:read, connections:writeIntegration connections
realtime:publishSignal 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.

Operator policy is an additional ceiling

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.

Identity belongs to a request

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.