Where is my workflow?
The instance page shows its status and each step with its status and times, so you see which step is running, which one waits for a person, and which one failed.
IdentityFlow runs long-running processes, such as approvals, that you write as async TypeScript functions. It records every step as an event in PostgreSQL, so an instance can wait days for a person, continue after the program restarts, and show afterwards what happened and who did it.
The instance page shows its status and each step with its status and times, so you see which step is running, which one waits for a person, and which one failed.
The Audit tab lists every recorded event in order, with its time and the account that caused it. Events are appended and never changed or deleted.
A dialog names the principals that may answer it. When an account answers, IdentityFlow asks your identity hook for the account’s current principals and refuses an account without a match.
A vacation request looks up the employee, then waits for an approver. The drawing shows what IdentityFlow records at each transition, and what happens when the instance continues after the answer.
load employee instead of calling the directory
again.
A Workflow Definition pairs an async function with a name, a version and an optional input schema. async (flow) => { … } is a function literal, like Go’s func(flow) { … }, and await waits for a step’s result.
flow.do('load employee', …) runs the lookup through a binding, the workflow’s named access to the directory, and records the result. On replay it returns that result without calling the directory.flow.dialog('approve vacation', …) waits until an account with the principal role:vacation-approver at the provider acme answers. The answer is checked against Decision.export const vacationApproval = defineWorkflow( { name: 'vacation-approval', version: '1.0.0', draft: false, label: 'Vacation approval', description: 'Request vacation and wait for an approver’s decision.', schema: VacationRequest, }, async (flow) => { const directory = flow.use(AcmeDirectory); const employee = await flow.do('load employee', () => directory.lookup(flow.params.employeeId));
// The completed lookup is reused when the approval resumes. const decision = await flow.dialog('approve vacation', { schema: Decision }, () => ({ params: { ...flow.params, ...employee }, assignees: [{ providerId: 'acme', subject: 'role:vacation-approver' }], }));
return { employeeId: flow.params.employeeId, decision }; },);The people who own a process and the people who build it read the same record.
Follow each request from the start form to the decision, and show afterwards who decided.
Write the process as an async TypeScript function and test it like any other code.
flow.do, flow.sleep, flow.dialog, flow.request and flow.startauthorization.ts grants access per workflowEach card links to the page that documents it.
Every change to an instance is an immutable event appended to its history in PostgreSQL. The state you see is derived from those events, and nothing edits or deletes them, so the same history is the audit record.
When an instance continues, finished steps return their recorded result instead of running again. Calls to other systems are delivered at least once.
A Workflow Definition pairs an async function with a name, a version and an optional input schema. Branches, loops and Promise methods are plain TypeScript.
A dialog waits for a person. The browser builds the start form from the input schema and the answer form from the dialog’s schema.
Access functions decide who may start, view, operate and audit each workflow, based on the principals your identity hook reports.
Tests start real instances in an isolated schema, act as declared accounts, answer dialogs and replace bindings with typed fixtures.
A binding is a workflow’s named access to an external system. 0.3.0 ships a GraphQL connector; for other protocols, the binding builds your own client.
Sleep until a date, wait for a person, poll an external job, start a child workflow or run steps in parallel. Each wait is recorded, so the program can restart meanwhile.
The code behind a deployed name and version never changes. Running instances continue on newer compatible versions of their definition.
A UI served from the same origin as IdentityFlow lists and answers the signed-in account’s dialogs and starts workflows through the GraphQL API. Reads return only what that account may see, and every command checks its authority.
Choose a task on Start here, or follow the tutorial to run the starter’s vacation approval as a requester and an approver. To see IdentityFlow with a process of your own, ask us for a demo.
IdentityFlow is provided to customers directly. If you don’t have the starter project and the IdentityFlow program yet, write to contact@kenoxa.de.