Orkestia
Blog
App Enablement

End-user data

Let a signed-in user run business logic through Orkestia — where the platform enforces that they only ever touch their own data.

Once a user is signed in, your app can have them run workflows — query their rows, place an order, send a message — by presenting their JWT. Orkestia injects the user's identity into the run immutably (the caller cannot set or override it), so a workflow can be written to only ever act on that user's data.

How it works

end-user JWT  ──►  POST /api/workflows  ──►  Orkestia injects the end-user principal
                                                      │
                                                      └──►  the workflow runs scoped to the user

Three rules the platform enforces for an end-user token:

  1. It can only start workflows you have explicitly exposed to your app.
  2. Only virtual (composed) workflows are startable — never raw platform workflows.
  3. The end-user principal is injected server-side from the verified token; an end-user-scoped workflow reads it and refuses to run without it.

1. Expose a workflow to your end-users

identity.app.expose-virtual-workflow({
  identity_app_uuid: "…",
  composition_uuid: "…",   // a composition you authored
  version: 1,
})

Every step in the composition must be marked end_user_eligible. A scoped data step (for example a structured, allow-listed read) is bound so its tenant filter is forced from the end-user's identity — there is no way for the caller to widen it.

2. Invoke it as the user

From your frontend, present the session token as a Bearer:

const res = await fetch('https://workflow-api.orkestia.dev/api/workflows', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${session.token}` },
  body: JSON.stringify({ workflow_type: 'virtual.<uuid>@1', initial_data: { /* free inputs only */ } }),
})
const { state_data } = await res.json()   // returns only this user's rows

The user supplies only the free inputs (a filter, a page size). The sensitive parts — which table, which tenant column, the connection — are fixed when you expose the workflow; the user can neither see nor change them.

Why this is safe

No data credential in your app

Your frontend never holds a database or API secret — Orkestia runs the workflow on its side.

Tenant isolation enforced

The user's identity is injected immutably and the scope is forced — one user can never read another's rows.

Audited

Every end-user action is recorded — see identity.end-user.audit-query.

This is the generic pattern behind any Orkestia-backed app: expose a capability, invoke it as the user, let the platform enforce the boundary. Step-by-step author → invoke → share → enable: Compositions. For declared tables see App Data — browsers still never send SQL; operators use Query. Mint the JWT with @orkestia/auth; start the virtual with the Node or Python workflow SDK. End-user HTTP without a virtual is PostgREST.