#Core Concepts
This page is the mental model. Each concept links to the guide that covers it in depth.
#Entities, types, and relationships
- An entity is a single data object. It has a
name, anattributesJSON blob, and belongs to exactly one entity type. - An entity type defines the shape: a JSON schema that validates
attributes, an identifier key (for upsert + de-duplication), and which attributes are indexed (sortable/searchable for queries). - A relationship rule declares that two types may relate (e.g.
Project → Task). A relationship is a concrete link between two entities under a rule.
Why flexible types? You evolve your data model without migrations — add a type, extend a schema, declare a new relationship rule, and start writing data.
#Querying
Two complementary read paths over the same data:
- REST query (
POST /entity/query) — composite filters, sorting, keyset/offset pagination, relationshipincludetrees, and counts. - GraphQL (
POST /entity/graphql) — a typed graph view with Relay-styleedges/node,where, andorderBy.
The two share the same underlying engine; a GraphQL query maps to the same filter/sort/include primitives a REST query uses. (You can convert one to a workflow step — see Querying & GraphQL and the converter at /graphql/.)
#Workflows, jobs, and actions
- A workflow is an ordered set of steps. Each step runs an action (create an entity, call HTTP, publish an event, …).
- A step can run an action inline, or invoke a referenced job — a reusable unit of work defined separately and called by name. Inline keeps small logic local; referenced jobs share logic across workflows.
- Smart values (
{{ … }},$jsonata,$literal,$if) thread data between steps and from the trigger payload.
Definitions live in the definition surface (/definition); a tenant
activates a definition (config + triggers) on the workflow surface
(/workflows), which runs it and records runs you can inspect.
#Triggers
A workflow doesn't run by itself — a trigger starts it:
- Event triggers fire on published events.
- Cron triggers fire on a schedule.
- Webhook triggers fire on an inbound HTTP call (with a per-trigger secret).
→ Triggers
#Bridge apps, specs, and widgets
A bridge app is the UI runtime. Its app spec defines dashboards →
pages → widgets (config-driven UI building blocks). The spec is a
definition; a tenant activates it on the app surface (/apps) with
config, integrations, principal overrides, and a token. At run time the spec
renders to a widget tree (POST /apps/run).
→ Apps (Bridge) · App spec structure · Widget Catalogue
#Principals, policies, grants, and shares
Access control has two tiers:
- Grants are intra-tenant: a tenant authorizes one of its principals (user / team / policy) to act on a resource, optionally narrowed by an attribute filter.
- Shares are inter-tenant and read-only: a tenant that owns a resource declares that another tenant may see it. A share never lets the other tenant write your data.
Cross-tenant data access needs both a share (from the owner) and a grant (in the consumer). This is what lets one tenant build on another's shared definitions or types without ever exposing the owner's rows to writes.
→ Shares & Grants · Provisioning
#Secrets
Tenant secrets hold credentials (API keys, tokens) that workflows and apps reference by name. Values are stored centrally and fetched by the engines at run time — never inlined into a definition.
→ Secrets
#Putting it together
The Canonical Example walks the whole chain on a single Tasks domain: model → workflow (inline + referenced job) → activation + monitoring → app spec (every widget) → app activation → provisioning → shares & grants → GraphQL→workflow conversion.