- host plugins.rs: PERMISSIONS, parse_permissions, ScriptPlugin.permissions/problems (None = legacy,
full API), validate_plugin (file name, 2 MiB, UTF-8 text without binary bytes, header with @name
and @version, valid @permissions, network:none refused when the code calls network APIs),
source_findings, PluginStore::install (atomic rename, never enables, keeps the enabled state on
update) / remove / is_enabled / file_hash. start/stop scripts run the module body, construction,
start() and stop() inside window.<global>.withPlugin(id, grants, fn) when the runtime has it.
- runtime permissions.ts: parsePermissions, scopePluginApi (undeclared gated members throw a
PluginPermissionError; scope().ui gated like api.ui), createPluginContext (the view of the plugin
whose code runs; legacy = full API). A declaration and guard rail, not a sandbox.
- The `commands` permission name comes from the parallel palette-commands work (its API lands there).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>