Workflows: the platform-wide approval engine¶
Every "Submit for Review" button on the platform runs through one shared engine — Workflows routes a proposed change through a configurable approval chain and lands the work in each reviewer's Tasks inbox.
Workflows is cross-cutting: business users rarely open the admin UI. They submit something, see under review, then approve / reject / request revision from their inbox. Admins design the chain once; every supported entity reuses it from then on.
When to choose this¶
-
Gate a change behind human sign-off
A glossary term, metric, insight, contract, or data asset can't go live until a reviewer consciously approves it.
-
Route work to the right reviewer
Resolve the assignee by role, entity owner, domain steward, or a submitter-picked user — automatically.
-
Enforce review SLAs
Deadlines with graduated reminders, escalation to a supervisor, and auto-expiry when a review stalls.
-
Standardise approvals platform-wide
Design one versioned approval chain and apply it to every entity of a type — no per-module approval code.
When not to reach for Workflows
- Executing automated, code-like work (HTTP calls, transforms, branching on data) → use Flows. The workflow engine is for human approval; Flows is for automated execution.
- Documenting a human procedure for reading → use Processes. Workflows runs the approval; Processes describes the work.
- Attribute-driven branching (route on risk level, change size, entity attributes) → model it in a Flow; workflow decision nodes branch only on the previous step's result.
How it works¶
A user proposes a change and clicks Submit for Review. The engine starts an instance, walks the active version's configurable approval chain, and creates one task per step in the assignee's inbox. Each approval advances the chain; the final outcome drives the entity's status transition.
flowchart LR
U["User proposes<br/>a change"] --> SUB["Submit for Review"]
SUB --> ENG(["Workflow engine"])
ENG --> CHAIN["Configurable approval chain<br/>ordered steps · assignee rules · SLA"]
CHAIN --> INBOX[("Tasks inbox<br/>one task per step")]
INBOX -->|approve / reject| ENG
ENG -->|all steps approved| APPLIED["Applied<br/>completion status"]
ENG -->|any rejection| REJECTED["Rejected<br/>back to draft"]
classDef accent fill:#ff8400,stroke:#e67700,color:#ffffff,font-weight:600;
class ENG accent
Figure 1 — One submission fans out into per-step tasks; each approval feeds back to the engine, which advances the chain and — on the final outcome — transitions the entity via its IWorkflowEntityHandler.
Why teams reach for this
One engine governs approvals for every entity type, so reviewers use a single inbox and admins maintain a single, versioned chain. The entity's status is driven by the workflow, not the user — nobody can quietly flip a metric to active without the review actually completing.
When workflows kick in¶
| Entity | What triggers a workflow | Module |
|---|---|---|
| Glossary term | Submit for Review on draft | Business glossary |
| Metric definition | Submit for Review on draft | Metrics |
| Insight dashboard | Submit for Review (publish gate) | Insights |
| Data asset | Promote to Certified / Archive | Data catalog |
| Data contract | Submit a new version | Data contracts |
| Module access request | User requests access to an inactive module | Administration → Modules |
(More entities can be added by registering an IWorkflowEntityHandler.) |
If the entity has no active workflow definition for its type, it transitions directly without review (configurable per entity).
What you'll see in the UI¶
| Surface | Where | What it does |
|---|---|---|
| Submit for Review modal | Detail page of the entity (when in draft status) |
Shows the workflow timeline, assigned roles, SLA per step, completion outcome. Submitter optionally picks the first step's assignee. |
| WorkflowProgress | Detail page of the entity (when an instance is active) | A horizontal step bar — completed steps in green, current step animated, future steps muted. Each step shows the assignee + SLA countdown. |
| Tasks inbox | /tasks |
Each step generates a workflow_step task for the assignee, titled by the item under review (Review "v1 of QA router"); the workflow and step are in its description. A bundle names the first item and counts the rest (Review "Revenue alert" and 2 more), and notifications and emails about the review name it the same way, in their text as well as their subject ('Revenue alert' and 2 more are awaiting your review in the 'Metric definition review' workflow). The emails, Teams messages and summary rows about the decision count the rest too. Approve / Reject / Request Revision lives here. After completion, a workflow_result task notifies the submitter. |
| Admin workflow builder | /admin/workflows |
Visual graph editor (React Flow). Drag step / decision / notification nodes; wire them with edges; pick assignee rules and SLA per step. Versioned. |
| Orchestration defaults | /admin/workflows |
Org-level default settings — timeout, assignee rule, escalation, max parallel branches, notification channel — that seed sensible initial values for new workflow / flow / process steps. Requires workflow.definitions.manage. |
Concepts¶
| Concept | What it is |
|---|---|
| Workflow definition | The reusable template — entity type, trigger statuses, completion / rejection statuses, ordered steps. |
| Workflow version | A snapshot of the definition's graph. Only one version is active at any time. Existing instances continue under the version they started on. |
| Workflow step definition | A node in the graph — defines the assignee rule, SLA, and (for decision nodes) the result-based branching. |
| Workflow instance | A running execution tied to one entity (e.g. Approve metric Net Revenue v2). Tracks current step + overall status. |
| Workflow step instance | One step of a running instance. Tracks assignee, linked task, result (approved / rejected / revision_requested), timing. |
| Webhook subscription | A governed outbound target the engine fires events to — paired with a connection-governance descriptor that gates delivery. See Webhooks below. |
| SLA policy | A timing template (deadline, reminders, escalation) attached per step. See Administration → Policies. |
Assignee rules — who gets the task¶
Each step picks one of:
| Rule | What it does |
|---|---|
submitter_picks |
The submitter chooses the reviewing group at submit time. A review goes to a group, never to one person. |
role_based |
Resolves to the first user holding a given organisational role, picked from the list of roles. |
auto_route_domain_steward |
Looks up a steward of the entity's domain who holds that entity type's approve role (used heavily by the metric approval workflow). |
entity_owner |
Routes to the entity's owner. |
specific_user |
Hard-coded to one user. No longer offered for a new step, because a review goes to a group; a step that already uses it keeps it. |
round_robin |
Rotates the task across a configured assignee pool — a persisted pointer advances to the next user in the pool on each new instance. |
least_loaded |
Assigns to the assignee pool member with the fewest open (pending / in-progress) tasks. |
org_role_team |
Routes to a selected organisational role team — the step is assigned to a chosen org role rather than a single named user. The submitter picks the team, so the picker offers only switched-on teams with a member other than them who holds the type's approve role, and any other team is refused with the reason. The choice is recorded in the audit log (review_team_chosen: who chose which team, for which item). |
When the engine picks a reviewer itself (role_based, auto_route_domain_steward and its fallback, round_robin, least_loaded, and an escalation to an organisational role), it never picks the built-in systemuser setup account, even though that account holds every role and is the oldest. A review routed there would sit in a shared login, and its approval would be recorded under that login. If the setup account is the only one left, the rule finds nobody and its usual fallback applies; an escalation whose only possible approver is the setup account leaves the review where it is. When Datahub checks whether a group can take a review, the setup account doesn't count as a member who could, and it can't be nominated as a reviewer. Two choices stay with an administrator: a specific_user step that names the setup account, and reassigning a task to it by hand.
The engine never silently fails to assign
If auto_route_domain_steward can't resolve a steward, the engine falls back to the organisational role the step names (Data Owner on the seeded workflows). Only a holder of that role who also holds the entity type's approve role counts. The seeded Data Owner role can approve every review the seeded workflows send it: data assets, glossary terms, alert rules, saved queries, workflow and flow versions, metrics, data contracts, data products, insight dashboards and integrations. Workflows, flows and metrics have no approve-only role, so the roles that let a Data Owner review them (from Workflow.ReviewApprover, Flow.ReviewApprover and MetricModule.Steward) also let them create and edit those; contracts and products bring write access. They don't include workflow webhooks, workflow or flow instance history, or version administration. The approve roles also make Data Owners deciders of the matching access requests.
When the role an auto_route_domain_steward or role_based step names has nobody who may approve, the review goes to a group that may, as that group's team task. That is the narrowest switched-on organisational role whose role groups give the approve role and that has someone other than the submitter who holds it, where narrowest means it grants the fewest rights. Administrator comes last. A role that is switched off, because it is deactivated or hidden from pickers, is passed over; Administrator is passed over only when it is deactivated. A role_based step that names a switched-off role doesn't send its review to that role's members, and an escalation to a switched-off role finds nobody and leaves the review where it is. Hiding a role only stops it being chosen: a team step that names a hidden role still sends its reviews there, and the role's members are told of the reviews in its inbox and may cancel them. The editor warns about such an escalation, and when it happens the task admins see it among the failed escalations in Tasks. On a one-person installation, where you are the only administrator and nobody else may approve, your own review goes to your group (usually Administrator) as a team task: claim it in Tasks and approve or reject it there.
When not even Administrator has someone who may approve, the engine falls back to submitter_picks and the modal asks the submitter to choose a group — never a single person: the lowest level a review goes to is a group. The preview response flags requires_submitter_pick and lists the groups the submitter may nominate (eligible_groups): switched-on organisational roles with a member other than the submitter who holds the approve role, with how many such members each has. It does so only for an item the submitter may submit. The picker for metrics, saved queries, flow and playbook versions, workflow versions, insight dashboards, glossary terms, data assets, dataset and document versions, data contracts and ownership contracts therefore only offers groups that can actually review, and the review becomes that group's team task. Ownership contracts have no approve role, so any switched-on group with a member other than the submitter qualifies. The nomination is recorded in the audit log (review_group_nominated: who chose which group, for which item), and the review task's history says whose inbox it went to. Until someone in the group claims the task, the review card says "Waiting on {group}", then names the member who claimed it. For metrics, saved queries, flow and playbook versions, workflow versions and ownership contracts, the confirmation after submitting says where the review went: "Sent to {group} for review", or, when it came back to you, a warning with a link to the review task. A group without such a member, or a named person, is refused with the reason. When no group has such a member, Submit stays disabled and the window says why: no group has a member other than you who may approve it. It names the groups whose members get that right, and the administrators who could add someone to one (an administrator is told to do it themselves). For workflow, flow, process, dataset, document, saved-query and alert versions, which the organisation's review requirement governs, it adds that switching that requirement off also lets the item go live without a review. The same fallback protects round_robin / least_loaded when the assignee pool is empty.
Decision nodes & graph routing¶
Workflows don't have to be linear. You can drop decision and gateway nodes into the graph and route based on the previous step's result:
- An Approval Step node has handles for
approved,rejected, and (optionally)revision_requested. - A Decision node branches on a condition (e.g. risk classification, requested change size).
- A Notification node sends a notification but does not block the chain.
- End Approved / End Rejected terminal nodes determine the entity's final status (drives the entity status transition via the
IWorkflowEntityHandler).
Pass-through (notification, decision) nodes are traversed transparently — they don't create tasks.
flowchart LR
START([Start]) --> S1["Approval Step<br/>assignee rule + SLA"]
S1 -->|approved| DEC{"Decision"}
S1 -->|rejected| ER[["End Rejected"]]
S1 -->|revision_requested| BACK["Back to submitter<br/>revise & resubmit"]
DEC -->|matches condition| NT["Notification<br/>non-blocking"]
DEC -->|else| S2["Approval Step 2"]
NT --> EA[["End Approved"]]
S2 -->|approved| EA
S2 -->|rejected| ER
classDef accent fill:#ff8400,stroke:#e67700,color:#ffffff,font-weight:600;
class DEC accent
Figure 2 — A step's result selects the outgoing edge. Decision and notification nodes are pass-through (no task); only End Approved / End Rejected set the entity's final status. Edges are wired by the admin in the builder.
The request lifecycle¶
The entity's status is driven by the workflow, not by the user. Submitting freezes the entity into under_review; the engine only releases it when the chain reaches a terminal outcome, calls the entity module's IWorkflowEntityHandler, and performs the actual status transition.
stateDiagram-v2
direction LR
[*] --> Draft
Draft --> UnderReview: Submit for Review
UnderReview --> Approved: Workflow completes
UnderReview --> Rejected: Reviewer rejects
UnderReview --> Draft: Withdraw / request revision
UnderReview --> Draft: Cancel (submitter, assigned team or person, admin)
UnderReview --> Expired: SLA expiry
Rejected --> Draft: Returns to draft
Approved --> [*]
Expired --> [*]
classDef accent fill:#ff8400,stroke:#e67700,color:#ffffff,font-weight:600;
class UnderReview accent
Figure 3 — The request lifecycle. On final approval the entity moves to its completion status (e.g. published, active); on rejection it returns to its rejection status (typically draft); the submitter or an SLA policy can end it early via cancel / expiry.
Submit for Review — the user experience¶
- User opens the entity detail page in
draftstatus. - Clicks Submit for Review.
- The shared
SubmitForReviewModalopens, showing:- The active workflow definition (name, description).
- Each step in order with the resolved assignee role + SLA badge.
- The completion + rejection outcomes.
- A reviewing-group picker when
submitter_picksapplies, or when routing found nobody who may approve.
- Submit. Entity transitions to
under_review. Reviewers see the task. If the review still landed on you, because no reviewer could be found and no group was chosen, the confirmation says so instead of "submitted" and links to the task. Withdraw it and submit it again with a group. - Each reviewer approves / rejects from their inbox.
- The engine advances to the next step automatically. On final approval, the entity transitions to its completion status (e.g.
published,active). On any rejection, it transitions to its rejection status (typicallydraft) and the submitter gets aworkflow_resulttask with the rejection reason.
SLA, reminders & escalation¶
Each step can carry an SLA policy (defined in Administration → Policies). The scheduler runs every few minutes and:
- Sends graduated reminders to the assignee at configured fractions of the deadline (e.g. 50% → soft, 80% → urgent).
- Escalates to a supervisor / role at the configured threshold.
- Auto-expires the task on policy-mandated expiry; the step (and instance) close as
expired.
Six standard SLA policies ship, spanning the fastest turnaround to the longest compliance window. Default is Standard Approval.
| Policy | Deadline | Role |
|---|---|---|
| Critical Escalation | 4 h | Fastest turnaround |
| Standard Approval | 48 h | Default |
| Compliance Review | 240 h | Longest window |
The Tasks inbox shows a countdown timer per task so reviewers always see how long they have.
Withdraw and cancel¶
- Withdraw is a module's own way to end a review, on the item's page. It returns the item to
draft, just as a cancel does. The same people may withdraw as may cancel: whoever submitted the request, the team or person it is waiting on now, and an administrator (tasks.admin). They also need the module's own edit role. Where the page can see the review, it offers Withdraw only to someone the review admits. Anyone else who withdraws, from the page or the API, is refused with a sentence that names who may. The refusal is recorded in the audit log, except for a playbook version's withdraw, which does not record it yet. - Archiving an item under review ends its review too, so it follows the same rule. This applies to a metric (single or bulk archive) and to a saved query. If someone the review does not admit archives it, the archive is refused with the same sentence and nothing changes: the item is not archived, and its review stays open. In a bulk archive, that row is reported as refused and the others go ahead.
- Cancel ends a review and returns the item to the status it had before it was submitted, usually draft. Only whoever submitted the request, the team or person it is waiting on now, and an administrator (
tasks.admin) may cancel. On pages that show the full review card, only they see the Cancel workflow button; a cancel from the API or an AI agent by anyone else is refused with that sentence. Pages that show the review as a status badge offer no cancel; use the module's own withdraw there, where it has one. - Who ended a review is on the record. Ending a review writes a Review cancelled entry to the audit log (Admin → Governance → Audit log), whether it ended through Cancel workflow, a module's withdraw, or archiving the item. The entry names who did it, and the line under it names the item, who submitted it and the step it was at. A refused cancel writes a Cancel attempt refused entry, naming who tried. To list these entries, set the log's Module filter to Workflows. To see one item's entries, open
/admin/governance/audit-log?entity_id=<id>, using the id of the item that was submitted. For a versioned item such as a flow or a dataset, that is the version's id. For a review of several items together, it is the id of the item the review was submitted from. Several modules also write their own Review withdrawn entry when the review is withdrawn. - Who rejected a review is on the record, for semantic models and saved queries. Rejecting a semantic model version or a saved-query version writes a Review rejected entry to the audit log. The entry names the reviewer who rejected it, and the line under it gives the version and the reviewer's comment. It is filed under the model's or the query's id, not the version's, so
/admin/governance/audit-log?entity_id=<id>lists it with the item's other entries. A withdrawn or cancelled review never writes one. Other versioned items, such as dashboards, flows, playbooks and alert rules, don't write it yet. For those, the rejection is recorded on the review itself: open the item's workflow progress and look at the step instance audit.
Retiring a workflow definition¶
Delete archives. It used to destroy the definition, its step definitions and the referent of every audit row about it — irreversibly, from a button labelled Delete.
| Action | What happens | Reversible |
|---|---|---|
| Delete | The definition is archived: it leaves the list, and the engine stops resolving it — new approvals are no longer started against it and it disappears from the submit preview. Nothing is destroyed. | Yes — Restore |
| Restore | Puts it back exactly as it was, including whether it was active. Find archived definitions with the Archived option on the workflow list's status filter. | — |
| Delete permanently | Destroys the definition and its step definitions. Audit entries about it lose what they refer to. | No |
Permanent delete only accepts a definition that is already archived — the server refuses anything else — so there is no single click that takes a live workflow to gone.
Archiving does not touch the definition's active/inactive flag: that flag is restored untouched, so Restore never has to guess at a state it did not change. It is the archive itself that stops the engine using the definition.
Running instances are unaffected: archiving retires a definition from being started again, it does not cancel work already in flight.
Webhooks — push events to external systems¶
Workflows is also the home of outbound webhooks. Platform events (workflow completed, workflow rejected, workflow step advanced, task completed, task overdue) can be subscribed to by creating a webhook subscription. Each subscription is paired with a connection-governance descriptor: outbound delivery is a governed connection, not a free-form URL fetch, and every dispatch is evaluated by the governance gate before anything is sent.
| Field | What it does |
|---|---|
| URL | HTTPS endpoint to deliver to. SSRF defence rejects private / loopback / link-local hosts at write-time and at every dispatch (DNS rebinding defence). |
| Event types | One or more event names to subscribe to. |
| Secret | HMAC-SHA256 signing key. Every delivery includes X-Datahub-Signature so receivers can verify authenticity. |
| Governance gate | Every dispatch is evaluated against the paired descriptor's egress allowlist, network posture, and state. A denied delivery is recorded (status denied, stamped with the governance decision) and never sent. |
| Retry | 3 attempts with exponential backoff (1m → 5m → 30m). |
| Receiver's answer | Datahub keeps the receiver's status code and reads at most 10 MB of its answer. A larger answer is not read further; the delivery log keeps the status code and, in place of the answer, a line that names the host and the limit ("Response not kept: The response from hooks.example.com exceeded the 10 MB limit on outbound HTTP responses"). A 2xx still counts as delivered, so the event is not sent twice. Redirects are not followed. Every attempt, retries included, also re-checks the subscription's host against its connection's egress allowlist and the private-network guard: a refused attempt fails at once and is not retried. |
| Delivery log | Per-attempt audit trail, linked to the governance decision. |
Common uses: notify Slack / MS Teams when a metric is approved, push a contract publication into a downstream catalog, kick off a CI pipeline.
Roles¶
| Role | What you can do |
|---|---|
workflow.definitions.manage |
Create / edit / delete workflow definitions. |
workflow.versions.manage |
Create, edit, activate, delete versions. |
workflow.instances.read |
View workflow instances and history. |
workflow.webhooks.manage |
Manage webhook subscriptions (outbound webhooks). |
The Workflow.Administrator role group bundles workflow.definitions.manage + workflow.instances.read + tasks.read.
Designing a workflow — the basics¶
/admin/workflows→ New definition.- Pick an entity type (must be one supported by an
IWorkflowEntityHandler). - Pick trigger statuses (entity status that fires the workflow, e.g.
draft → under_review), completion statuses (e.g.[active],[published]), and rejection status (typically[draft]). - Drag steps onto the canvas. Each step picks an assignee rule and (optional) SLA policy. A step that sends its reviews to a group (Role-based, Org role team, a Domain steward step's fallback role, or a role-based escalation) picks that group from the list of organisational roles.
- Wire the edges. For multi-outcome steps, label the edges with
approved/rejected/revision_requested. - Drop terminal nodes (End Approved / End Rejected).
- Save → activate. The graph compiles into ordered step definitions; the active version is now in force for new instances.
The editor warns about reviews nobody can approve. Approving a review needs the item type's approve role (for example flow.definitions.manage for a flow version), whoever the review was sent to. While you edit, and again when you save, the editor checks every group a step sends reviews to. A warning under the header names each step whose group can't approve them, for example "Step 'Review': nobody in Finance Team may approve this, so its reviews can never be approved.", and the step's settings show the same line under the field. It also warns when the group no longer exists, is switched off, or has nobody who can sign in, and when a value is not an organisational role (a role name typed in the old free-text field is never found). When only one person in the group may approve, it notes that this person can't approve their own submission. On a role based step it also warns when only some of the group may approve: such a step sends each review to the first member who didn't submit it, who may be one who can't. Membership changes on its own, so the check runs each time and is never stored. Fix it by picking another group or by asking an administrator to give the approve role to someone in the group. The warning does not stop you saving or submitting.
Admins hear about it without opening the editor. Every 15 minutes Datahub runs the same check on the version each live workflow runs. When a step there has a warning, the Administration page counts the workflow among the checks that need attention, and everyone who holds workflow.definitions.manage gets one bell notification that opens the workflow list. When nobody holds that permission, the people in the Administrator organisation role are told instead, or, when there are none, those in the Administrator role group. Only a warning counts. A note, such as a group where one person may approve, or a step whose reviews go to the next group that may approve them, still sends its reviews to someone who may decide them. A draft, switched-off or archived workflow is not counted, and a step you fix counts as fixed once its new version is active. Once nothing is left to fix, the next check takes the notification out of the bell.
When your organisation requires review, step 7 is Submit for review instead. The version's own review goes to a steward of the workflow's domain, or a Data Owner, who holds workflow.definitions.manage. The submit window names that reviewer, or, when nobody there may approve it, asks you to choose a group with someone who may.
Limitations¶
| Limit | Why | Workaround |
|---|---|---|
| Only one active version per definition. | Avoid ambiguity. | Existing instances continue on their original version. |
| Existing instances don't migrate to a new version. | Auditability — instance must be reproducible. | Cancel + restart if the new version must apply. |
| Decision nodes evaluate on the previous step's result, not on entity attributes. | Engine simplicity. | Use a Flow (Flows) for attribute-driven branching. |
| Webhook deliveries are best-effort with finite retries. | Receiver may be down. | Inspect delivery log; manually re-dispatch from the admin UI. |
| Workflow steps can't run arbitrary code. | Security. | Use Flows for code-driven automation; trigger the flow from a workflow step's notification node. |
| The engine does not understand "and / or" parallel approvers. | Single-track for now. | Model as sequential steps; planned. |
Audit & compliance¶
| Question | Where to look |
|---|---|
| "Who approved this metric?" | Detail page → workflow progress → step instance audit. |
| "Who rejected this semantic model or saved-query version, and why?" | Admin → Governance → Audit log: a Review rejected entry names the reviewer, the version and their comment. |
| "How long did the review take?" | Each step instance has start / end timestamps. |
| "Did the SLA fire?" | Reminder log table; policies event stream. |
| "Was the webhook signed?" | Yes — every dispatch includes X-Datahub-Signature (HMAC-SHA256). |
| "Can a reviewer approve their own submission?" | Workflow definitions can require a different reviewer than the submitter (configurable per step). |
| "Where do webhook URLs go?" | Stored against the subscription; SSRF-validated at write time and on every dispatch, and gated by the paired descriptor's egress allowlist. |
| "Was an outbound webhook allowed to fire?" | Every dispatch persists a connection-governance decision (allow / deny + reason); the delivery log links to it. |
Troubleshooting¶
| Symptom | Likely cause | Fix |
|---|---|---|
| "Submit for Review" button missing | No active workflow definition for the entity type — entity transitions directly. | /admin/workflows → register a definition. |
| Reviewer sees no task | Assignee rule didn't resolve. | Check the workflow step instance — submitter_picks fallback should engage automatically; if not, file a ticket. |
Workflow stuck in under_review |
Step task is not approved + no SLA expiry. | Check the inbox of the assignee; reassign if needed. |
| Approve says "Your approval was not recorded" | The item under review cannot take effect yet, for the reason shown (for example, a flow whose ownership contract is not published). Nothing was approved and the review is still open. | The notice says whether the reason can be fixed while the review stays open. If it can (an ownership contract still in its own review), approve again once it is fixed. If it cannot (something that was submitted has to change), choose Reject with this reason to send it back to the submitter. |
| Webhook deliveries failing | Receiver returned 4xx/5xx, or URL was rejected by SSRF defence. | /admin/workflows → webhook detail → delivery log. Edit URL if rejected. |
| Webhook signature mismatch on receiver | Receiver computing HMAC differently. | Use HMAC-SHA256 over the raw body with the registration secret; header is X-Datahub-Signature. |
| "Submit for Review" modal lists wrong reviewers | Workflow definition's assignee rules don't match your org. | Edit the definition + activate a new version. |
See also¶
-
The inbox where reviewers actually approve / reject / request revision.
-
Attribute-driven, code-like automation. Workflows is for human approval; Flows is for automated execution.
-
Model the human side of the work; Workflows runs the approval gate on top of it.
-
One of the entities whose Submit for Review button is powered by this engine — alongside Metrics, Insights, Data catalog, Data contracts.
-
The SLA templates that drive per-step deadlines, reminders, and escalation.