Addons

Sandboxed React mini-apps that extend your workspace — concept and security model.

An addon is a small React app that you write and that runs inside your workspace — full-screen at /addons/{id}, or embedded as a block in any document. It's how you add custom UI and workflows to Dalea without shipping a separate application or waiting on the platform team: a bespoke sample-intake form, a specialised visualiser, a one-off calculator that reads your tables and writes back a result.

Where the SDK and MCP let code run outside Dalea and reach in, an addon runs inside the product UI — sharing the host's theme, session and data. It carries no credential of its own. Its only line to the platform is a capability proxy called dalea, and every call it makes is checked, host-side, against the permissions you granted.

Why addons exist

Every lab eventually wants a screen the platform doesn't ship: a plate-layout designer, a dosing calculator, a "register these ten samples the way we do it" form. The choices used to be a spreadsheet macro nobody trusts, or a feature request that waits a quarter. An addon is the third option — a focused mini-app, authored in-workspace, that lives right next to the data it works on and is governed by the same permission model as everything else.

Where an addon appears

An addon declares one or both surfaces in its manifest:

page
A full-screen app at /addons/{id}. Good for tools people open and work in — designers, dashboards, bulk-entry forms.
block
An embeddable block inside a document. Good for a live widget that lives alongside written protocol — a calculator, a small chart, a status panel. Each embed gets its own configuration.

The security model

Addons are untrusted code by default, and the runtime is built around that assumption. Four properties do the work:

Sandboxed iframe
Every addon renders in a cross-origin iframe. Its Content-Security-Policy blocks all external network access — no fetch or XHR to any origin. If an addon needs data it goes through dalea; if it wants an external resource, it can't have one.
No credentials
The iframe holds no session and no token. It cannot see your cookies, call the REST API directly, or act as you outside the capability proxy.
Scope-checked calls
Every dalea.* call is validated on the host against the scopes the addon declared and you consented to. A call outside the granted set is rejected — the addon never touches anything you didn't approve.
Workspace-pinned
The target workspace is fixed host-side. An addon can never reach into another workspace, whatever it asks for.

An addon requests a subset of nine coarse scopes, and you see exactly which before it runs:

Data
data.read, data.write — environments, tables, columns, objects, queries, results.
Documents
documents.read, documents.write — read and edit documents and their markdown blocks.
Inventory
inventory.read, inventory.write — lots, containers, placements, consumption (operational only — no type/schema management).
Search
search.read — the unified workspace search.
Storage
storage.read, storage.write — list, fetch and upload files.

Two more guarantees are baked into the capability surface itself. There are no hard deletes anywhere — the destructive path is archive, reversed by restore — and calls are rate-limited per instance, so a runaway loop can't hammer the platform.

Least privilege, by construction

An addon that only declares data.read physically cannot write, delete, upload, or reach the network — not because it promises not to, but because the host rejects anything else. That's what makes it safe to run a mini-app a colleague (or an AI assistant) wrote without auditing every line.

The human enablement gate

An addon created in the browser is self-enabled — the person authoring it is the review. But an addon created programmatically — over the REST API, or by an AI assistant through MCP — starts disabled. It can be edited and built, but it will not run anywhere until a person opens /addons/{id}, reads the permissions it requests, and clicks Enable. That step provisions the addon's workspace app and generates its permission-ceiling role. If a later change widens the scopes it asks for, enablement is revoked and a human must approve again. Machines can write an addon; only a person can turn it on.

Lifecycle at a glance

1 · Create
Make an addon in the app or over the API. Programmatic ones start disabled.
2 · Author
Write the scripts, declare a manifest, map the workspace entities it references. See Authoring an addon.
3 · Enable
A person reviews the requested permissions and turns it on (automatic for browser-authored addons).
4 · Build
The source compiles to a runnable bundle with your entity mappings substituted in.
5 · Publish
Optionally share it to the community marketplace as a bundle. See Publishing & installing addons.
6 · Install
Another workspace installs it, re-maps it to their own entities, and runs it.

Addons vs. the SDK vs. MCP

All three are ways to build on Dalea; they sit at different places.

RunsTalks to Dalea viaBest for
AddonInside the app UI (sandboxed iframe)The scoped dalea proxyCustom in-product screens and document widgets
SDKYour own code, anywhereREST + your API key / OAuthScripts, backends, integrations that reach into Dalea
MCPAn AI client (Claude, a custom agent)Bearer-authed MCP toolsLetting an LLM read and act on a workspace

The addon surface is a deliberately narrower subset than the full public API — no destructive operations, no cross-workspace reach — because addon code is the least trusted of the three.

What's next