Appearance
Apps
An app adds an integration to a tenant, usually a vendor: actions that workflows and rules call, and, when the vendor answers later or needs the applicant, a webhook handler and a hand-off to the vendor's browser SDK. An app is a WebAssembly module. A tenant installs it with its own configuration and secrets, and the platform runs every call of it in a sandbox that holds that tenant's data for that one call.
Platform apps and tenant apps
- Platform apps ship with each release, in the catalogue (
catalog/in the repository):mock-sanctionsanddoc-verify-mock(deterministic mocks, no vendor account) andopensanctionsandsumsub(the reference vendors). Every tenant sees them. See App catalogue. - Tenant apps are modules a tenant's administrators upload. Only that tenant sees them, and they can be installed once published, after another administrator's approval when the tenant requires one. See Apps: authoring.
Whatever its kind, a tenant installs an app under its name (opensanctions, acme-screening), picks the version, fills in the configuration the version declares, approves the hosts it calls and stores its secrets. Two tenants never share an install, a configuration or a secret. Workflows call an install with a call_app step and rules with the app rule type, by its name and an action.
How a call runs
The app runner (apps/app-runner) is a service of its own, with no database connection, no storage credentials and no key to the secret store. The worker and the API hand it each call with everything the call needs: the module's hash, the install's configuration, its approved hosts, its secrets (decrypted for this call) and, for an app that reads documents, a token for the tenant's documents that expires in five minutes. The runner fetches the module from the API by its hash, instantiates it afresh, runs one export and discards the instance, so nothing a call holds survives it.
Inside the sandbox a module has no file system, no sockets and no network of its own. It reaches the outside through five host functions, each bound to the call's tenant: http_request (to the install's approved hosts only), hmac, hmac_verify, document_read and log. A module names a secret with a placeholder and the host puts the value into the outgoing request, so the value never enters the module; every string that leaves a call (an error, a log line, the module's answer) is cleared of the call's secret values. See Apps: host interface.
Trust
A tenant that installs an app trusts its author with that install's configuration, secrets and documents, towards the hosts the version declares. The console lists those hosts before an install and before an upgrade that adds one, and the install records the hosts it approved; the runner refuses every other host and every private address whatever the name. Platform apps' hosts are reviewed with the catalogue. Nothing lets an app reach another tenant, the platform's credentials or a host the install did not approve. An operator can stop a module everywhere by its hash (APP_BLOCKED_SHA256): every call of it then fails with app_blocked.
Turning apps on
Apps run when the deployment has object storage (the modules live there) and an app runner (APP_RUNNER_URL on the API and the worker). When either is missing, the API answers /apps routes with 503 apps_unavailable, the health summary reports apps: off, and a call_app step fails with that reason. Deployment lists the settings: the runner's bearer token, the API's internal listener, the call-token secret, the catalogue directory and the secret store key.
Where to go
| You want to | Read |
|---|---|
| Write an app, test it and upload it | Apps: authoring |
| Look up a manifest field, a limit, a route or code | Apps: reference |
| Write a module without the TypeScript SDK | Apps: host interface |
| Install a platform app or configure a vendor | App catalogue |
| Read the SDK's exports and types | App SDK reference |
| Manage apps in the console | Admin console: Connect |