Skip to main content

Capabilities

Capability mediation is mandatory: every interaction between a solution and the host platform passes through the capability registry. A solution has no side door — no direct database, Redis or network access — and the capability layer is the single gate.

Host capabilities

Capabilities a solution UI may request in the manifest's capabilities list:

CapabilityMeaningGrant condition
theme.getRead host/solution theme tokensAlways granted
user.getRead current user profileAlways granted
tenant.getRead tenant metadataAlways granted
runtime.queryQuery own runtime data (metrics / executions / workflows)Always granted
workflow.triggerTrigger this solution's workflowsRequires manifest permission workflow.execute
customer.queryQuery customer-hub dataRequires manifest permission customer.read
connector.invokeInvoke declared connectors through the bridgeRequires ≥ 1 declared connector
storage.readSDK may read documents via ctx.storageRequires storage.read permission
storage.writeSDK may insert via ctx.storageRequires storage.write permission
storage.updateSDK may patch via ctx.storageRequires storage.update permission
storage.deleteSDK may soft-delete via ctx.storageRequires storage.delete permission

Unknown capability names are rejected at publish time. Reserved SDK namespaces (storage, vector, …) cannot be registered as connectors — see Managed storage.

Requesting capabilities

Requested capabilities are declared in manifest.yaml:

manifest.yaml (excerpt)
capabilities:
- theme.get
- user.get
- tenant.get
- runtime.query
- workflow.trigger
- storage.read
- storage.write
- storage.update
- storage.delete

The install wizard shows this requested set next to the granted set before activation — tenants always see what they are approving.

Negotiation

The granted set is the intersection of what the package requests and what the installation can grant:

  • Computed at install time and stored with the tenant bundle.
  • Re-checked on every invocation — a granted set is not cached trust.
  • Recomputed on upgrade; the wizard surfaces any change.

Example: [email protected] requests workflow.trigger and storage.*, declares matching permissions, and sets connectors: [] — storage capabilities authorize the SDK’s ctx.storage; connector.invoke is not granted. UI sources target restaurant-pro/restaurant.* and gate on runtime.query. An older package that declared a POS connector would also negotiate connector.invoke for bridge-backed sources.

The ui.* host API

The portal implements the host API in-process; every call is checked against the granted set:

CallEffect
ui.registerRegister the UI with the host (idempotent; returns granted capabilities)
ui.navigateNavigate to a declared page (validated against the bundle)
ui.emitEmit a ui.* lifecycle event onto the event bus
ui.subscribeSubscribe to capability-gated host signals
ui.capabilitiesReport the granted capability set

Solution authors never call these directly — widgets, forms and navigation entries map onto them through the declarative definitions. The calls are documented so capability failures are diagnosable.

Capability-gated data

Every data-source fetch is gated the same way:

A widget whose capability is not granted never fires a request. This is why a missing permission renders as a calm empty state rather than a permission error.

Restaurant Pro granted set (1.7.0)

RequestedGranted?Why
theme.get, user.get, tenant.get, runtime.queryYesAlways granted
workflow.triggerYesworkflow.execute permission declared
storage.read / write / update / deleteYesSDK ctx.storage — matching permissions
connector.invokeNoconnectors: [] — not requested