Runtimes & capabilities
Preview Every site carries a runtime, and
each runtime advertises a set of capabilities — the actions it can actually
perform. A client asks a site what it can do
and branches on the answer, instead of hard-coding if runtime == "wordpress". This
page is the reference matrix: which capability each runtime supports, and what “no”
means when it doesn’t.
discover at runtime, don’t hard-code
Section titled “discover at runtime, don’t hard-code”The platform answers the question for you. Call GET /v1/sites/{id}/capabilities
for one site, or GET /v1/runtimes for the static catalog of every runtime and its
default capabilities and component kinds.
{ "data": { "runtime": "wordpress", "runtime_version": "6.8", "capabilities": { "components.plugins": { "supported": true, "actions": ["list","install","activate","update","delete"] }, "components.themes": { "supported": true, "actions": ["list","activate","update","delete"] }, "components.users": { "supported": true }, "components.content": { "supported": true }, "cron": { "supported": true, "kind": "wp-cron" }, "database": { "supported": true, "engine": "mysql" }, "exec": { "supported": true, "shells": ["wp-cli","bash"] }, "magic_link": { "supported": true }, "clone_content": { "supported": true, "selectors": ["db","files"] }, "build": { "supported": true } } } }the matrix
Section titled “the matrix”Rows are runtimes; columns are capabilities. A cell shows the supported actions, or
false when the runtime can’t do it at all.
| Capability | wordpress |
static |
drupal roadmap | node roadmap |
|---|---|---|---|---|
components.plugins |
list · install · activate · update · delete | false |
false |
false |
components.themes |
list · activate · update · delete | false |
activate · update | false |
components.modules |
false |
false |
list · install · enable · update | false |
components.users |
CRUD | false |
CRUD | false |
components.content |
posts · pages · media | false |
nodes · media | false |
cron |
wp-cron |
false |
drush-cron | scheduler |
database |
mysql |
false |
mysql/postgres |
false |
exec |
wp-cli · bash |
false |
drush · bash |
bash |
magic_link |
SSO into wp-admin | false |
SSO into /user |
false |
clone_content |
db · files | files | db · files | files |
build |
supported | supported | supported | supported |
the two “no” semantics
Section titled “the two “no” semantics”A capability being unavailable is reported one of two ways, and the difference is deliberate — see errors:
- Structurally absent →
404. The capability doesn’t exist on this runtime and a scope-limited key couldn’t even hold a scope for it. Asking astaticsite for its plugins returnsnot_found, the same as a resource you can’t see — existence hiding. - Route exists, runtime can’t →
409 environment.capability_unsupported. The endpoint is real and you’re allowed to call it, but this runtime can’t perform the action. Installing a plugin on astaticsite is a409, withparamnaming the offending field.
Discover capabilities first and you avoid both — the matrix and the discovery endpoint exist precisely so you never have to guess.
adding a runtime is a catalog entry
Section titled “adding a runtime is a catalog entry”The whole point of this model is that a new runtime inherits the entire platform — auth, jobs, SSE, observability, billing — for free. Bringing one online is two pieces of work, neither of which touches the foundational resources:
- A runtime-catalog entry describing its default capabilities and component
kinds (what
GET /v1/runtimesreturns). - A capability provider on the agent side that implements those capabilities —
e.g. mapping
components.modulestodrush.
No new endpoints, no new scopes, no foundation change. A static site and a WordPress site are the same resource type with different advertised capabilities — that’s the entire trick. See build runtimes for how detection and the build pipeline fit in.