Docs · Extend
Plugin permissions
Who wrote a plugin grants it nothing. Beyond a small base, every capability is an Owner grant bound to the exact version, and a new version asks again.
The rule behind every plugin in Caelo: who wrote a plugin grants it nothing. A plugin gets a small base set of capabilities. Everything beyond that is a grant the Owner approves for one exact version of the plugin. This page describes the model and states plainly where the current release does not meet it yet.
The base: no grant needed
- Its own public tables, declared in the manifest schema, read and written through
ctx.query. Row-level security scopes every row to the plugin. Another plugin cannot read them, even if its code tries. ctx.api: the plugin's own public read surface for its Web Component.ctx.theme: read-only theme tokens.ctx.visitor: an opaque visitor id, the public user id and an IP hash. Never the visitor's session token.ctx.captcha: whether the API gateway verified the visitor's proof-of-work for this request.ctx.invocation: who the call acts for.publicOperations: the operations a visitor may call through the gateway. Everything else is refused.
Grants for runtime-installed plugins
A plugin installed at runtime can be granted these today:
| Grant | Allows |
|---|---|
Private storage (cms_admin_schema) | Tables in the plugin's own private schema, for author-side data no visitor may read |
Chat tools (chat_runner_tools) | The plugin's operations as AI tools |
Companion skills (companion_skills) | Guides for the AI that ship with the plugin, at most 20 |
Private files (private_files) | Immutable author-side files |
Image generation (image_generation) | Image calls brokered by Caelo; requires private files too |
Font library, read (font_assets) | Reading the site's fonts |
Site media, read (site_media_read) | Reading the media library |
The full model also names per-domain core-data read and write, AI provider calls, background workers, email, client assets (a script on every page) and structured contributions (head, sitemap, URL slots, data lists). Caelo has no broker for those yet for runtime-installed plugins. A plugin that requests one can be reviewed but does not activate.
A plugin never receives a key, a database connection or a raw handle. The host brokers every grant and re-checks it on every call.
How approval works
A plugin that requests grants is reviewed at Settings → Plugins → Install external packages and review access (/settings/plugins/installations). Plugins the AI builds with extra access land in the same queue. Approving needs the plugins.install permission, which only the Owner holds by default.
- You see everything the AI will see. The exact source, the manifest, the stated reason for each grant, and every tool name and description.
- Each grant is its own checkbox, none preselected. In this release you must approve every requested grant; declining one leaves the plugin inactive.
- Approval issues a receipt per grant, bound to the SHA-256 digest of the manifest and source. A manifest that lists a grant gets nothing by itself; only receipts count.
- A new version asks again. It is a new artifact with a new digest. The running version keeps running while you review the replacement.
- Revoking a grant disables that version and keeps its data. A write already accepted finishes; no write starts after the revocation. You can revoke at
/settings/plugins/installations, or ask the AI: it lists grants withlist_plugin_grantsand proposes the revoke withpropose_revoke_plugin_capability, which you approve. - Private storage is for authoring only. The plugin gets it when it acts for someone who may author content: in a chat, in the Owner panel, or for an action you approved. Rendering and visitor calls never get it.
Rules no grant can lift
- Own data, or granted interfaces. A plugin never touches another plugin's data. It reaches core data only through named operations of a granted domain. No table access, no SQL.
- No direct writes to live. Authoring writes are validated, audited and snapshotted. From a chat they land in the draft and go live only when a person publishes. The one exception is a visitor's write into the plugin's own public tables, such as a form submission.
- Nothing runs before activation, and only a human Owner activates or grants.
- Hard-to-revert actions, such as changing the site's URL strategy, additionally ask for your click in the chat, every time.
Where the current release falls short
Caelo is pre-1.0. The requirements list these gaps as tracked defects:
- Shipped plugins run in-process and get their capabilities at load, not through per-version Owner grants. They are not sandboxed. Their access to core data is one broad capability rather than per-domain grants.
- Chat tools of shipped plugins still write their public tables live, for example comment moderation from a chat.
- A render call's access to core operations is not yet refused for writes.
- Some host code that brokers for plugins (event polling, AI cost accounting, the per-operation audit row, plugin registration) still issues SQL directly instead of named operations.
Next
Something wrong or missing on this page? Open an issue on GitHub