Reviews and workflows
The server has two ways to control how a revision gets released: review rounds, built into every revision, and workflows, processes an administrator draws for anything more involved. Both can be used together.
Review rounds
Submitting a revision for review moves it to In review and opens a review round on it. The round holds its reviewers, how many approvals it needs, whether the submitter's own approval counts, an optional due date, and every decision. When submitting you can add reviewers, set a due date and post a first comment.
- Reviewers decide with Approve or Reject. Each person's latest decision counts once. A rejection needs a comment; it ends the round and sends the revision back to Draft. The next submission opens a new round.
- Approvals are on a version. Each decision records the document as it was. Saving during review is allowed, but an approval given before the save shows as on an older version and stops counting until its reviewer approves again. A release refused for this says how many approvals need renewing.
- Pulling a revision back to Draft withdraws its round.
- The submitter can change the round's reviewers and due date; the
checkingroup can also change how many approvals it needs. - Discussion. Every revision has a threaded discussion. Anyone except viewers and workers can comment and answer comments.
The review rule
How many approvals a release needs, and from whom, is the review rule in Server
settings: the number of approvals, a due period, the reviewers (users and groups, written
user:grace or group:quality; with none, the checkin group decides) and whether
self-approval counts. Overrides give a different rule to a category (and everything
beneath it) or to a part type; the nearest category override wins, then the part type's.
The default rule needs 0 approvals, so until an administrator sets one a draft can be released directly. The rule is copied into a round when it opens, so a settings change applies from the next submission.
The inbox
Inbox lists what waits on you (rounds where you are a reviewer, workflow tasks assigned to you) and what you submitted. Its badge in the top bar counts what waits on you. Review requests can be approved or rejected directly from the inbox.
There is no built-in email. To notify people, an administrator writes a
review-event.js script, which hears every review event and can post to a chat or
mail service (see Scripts).
Workflows
Workflows lists the processes you may start and the runs you started or take part in. Administrators build process definitions in Administration → Workflow editor.
Drawing a process. Drag steps from the palette onto the canvas and connect an output
to an input. Each connection's outcome is always, success, reject or a custom
outcome a script returns. A process needs one Start and at least one End, every step
reachable from Start, and no cycles. A fork runs its branches independently; a join waits
for every incoming path to finish with a matching outcome, so a rejected review cannot
pass a join and release a model.
Steps include:
- Review steps: their reviewers are resolved when the process starts and approve in parallel. Required approvals of 0 means every assigned reviewer. Self-review is off unless enabled.
- Forms: fields of text, multi-line text, numbers, yes/no and choices. Each field
says who may read and edit it (
user:<name>,group:<name>,initiator,assigneeor*) and at which steps it must be filled. The server checks types, required values and permissions, and never shows a field to someone who may not read it. - Decision steps, where an assignee chooses which path the process takes.
- Status steps, which move the revision through the normal lifecycle with all its checks.
- Check, Script and Decision script steps, which run administrator JavaScript (see below).
- Fork and Join, which split and rejoin parallel paths.
Forms and reviews arrive as Inbox tasks. The run's page shows its progress, the decisions, and a log of who did what, which steps ran or were skipped, and what changed. Script output and errors are shown only to administrators.
Versions. Saving a definition makes a new version. A run keeps the version, graph, assignees and fields it started with, so editing a definition affects only later runs. A definition can be made inactive, limited to some part types, and limited to the users or groups who may start it. With no start list, authors may start it; a list can let other groups submit forms without being able to edit models.
Release only through the workflow. Marking a definition Require this workflow for part release stops direct release of the part types it applies to: the release must come from that workflow's release step. A workflow containing a model review pins the document it reviewed; editing the model means starting a fresh process.
Script steps define step(input) and return { outcome: "success", fields: {...} },
a custom outcome, or false for reject; throwing fails the step. The input carries the
run, step, part, revision, document hash, field values, initiator, attempt number and a
stable idempotencyKey (runId:nodeId). A step that calls an outside system (an ERP
order, a vendor upload) is committed as dispatched before it runs, so it is never run
twice by accident. If the server restarts mid-step, the step is marked failed rather than
silently run again. Administrators retry failed steps from their inbox; give the
receiving system the idempotency key so a retry cannot double an order. The initiator or
an administrator can cancel a run while no automatic step is executing.
Scripts
Administrators customise the server with JavaScript files in the scripts directory
(--scripts, default <data>/scripts). The directory is the source of truth: keep it in
git if you like. The server re-reads a file when it changes, so a git pull takes effect
on the next call without a restart. Administration → Scripts edits the same files in
the browser and test-runs them.
| File | Function | Runs |
|---|---|---|
| named by a Script-mode part type | partNumber(input) | creating a part of that type |
revision-label.js | revisionLabel(input) | creating any revision; null accepts the typed label or the suggestion |
before-release.js | beforeRelease(input) | before a release commits; a throw refuses the release |
after-release.js | afterRelease(input) | after a release commits; a throw becomes a warning |
reviewers.js | reviewers(input) | submitting a revision for review |
review-event.js | reviewEvent(input) | after every review event |
Each function takes one JSON argument and returns JSON. If a hook throws, the operation is refused and the user sees the thrown message, except where the table says otherwise.
Scripts are fully trusted. They can make HTTP requests (http.request), read and
write files (fs), run programs (process.run), and read and change PLM data (plm.*).
An administrator who can edit scripts in the browser can therefore run any program on
the server. Turn the editor off in Server settings, or start the server with
--lock-script-editor so no administrator can turn it back on. Scripts keep running
from the directory either way.
A test run is a real run: test-running a script that posts to your ERP really posts.
Loops are limited to ten million iterations and calls to a depth of 512, and an HTTP request times out after 30 seconds unless it asks for another limit. There is no overall time limit on a script, and a program it runs is not limited at all.
A notification takes a few lines:
function reviewEvent(input) {
if (input.event !== 'opened' && input.event !== 'reject') return;
const s = input.subject;
http.request({
url: 'https://chat.example.com/hooks/plm',
method: 'POST',
body: { text: `${s.number} rev ${s.label}: ${input.event} by ${input.user.username}` },
timeoutMs: 5000,
});
}