The three screens you land on before opening anything.
| Route | File |
|---|---|
/ | app/page.tsx |
/processes | app/processes/page.tsx |
/templates | app/templates/page.tsx |
/start/[templateKey] collects runInputs and evaluates startExpression before
creating a process.
/ — DashboardFour stat cards, a recent-activity feed, and per-process avatars. Loads everything from a
single GET /api/process and computes in the browser.
| Card | Computed from |
|---|---|
| Active Processes | status === "running" |
| Awaiting My Sign-off | hardcoded 0 — never computed |
| Completed This Week | status === "completed" and updatedAt within 7 days |
| Avg. Completion Time | mean of updatedAt − startedAt over completed runs |
The whole dashboard is replaced when a skin sets HomePage — see
whitelabel. The Allocation Risk skin substitutes
ConduitPipelineHome.
/processes — Active ProcessesThe real working list. Search, three filters, four sort orders, inline start, inline delete, and a progress bar per run.
| Control | Options |
|---|---|
| Search | free text |
| Status | all · active · completed · rejected |
| Template | all, or one template |
| Sort | activity ↓↑ · started ↓↑ |
Loads GET /api/process and GET /api/process-templates together, so it can offer
"start a run" inline and label each row with its template.
This list does what the platform does not — it derives failure:
function displayStatus(p: Process): DisplayStatus {
if (p.status === "running") return "active";
const r = p.result;
if (r?.outcome === "rejected" || r?.status === "rejected") return "rejected";
if (typeof p.error === "string" && p.error.length > 0) return "rejected";
return "completed";
}
Three signals, none of them status, because status cannot express it.
So / and /processes disagree about the same run. The dashboard counts it as
completed; the list shows it rejected. Both are reading the same document.
That is the third independent re-derivation of "did this fail?" in the codebase — this
one, RecordOutcome in records, and the progress-bar tone below. Each
would become unnecessary if
ProcessStatus had a failure state.
den = template.steps.length num = index of the current step in template.steps
It counts a step's position in the array against the array length. But array order is
meaningless — the run follows nextStepKey. A template whose steps are declared out of
order, or one that branches or loops, will show progress that jumps backwards or sits at
90% through a rework cycle.
It reads as a completion percentage and is not one.
/templates — Template listLists templates with a status badge (active / draft / archived), an active-run count
per template, and a per-row menu.
The menu offers View (the read-only template viewer) and Start. There is no New Template or Clone: templates are code-owned and published on deploy (see manage templates).
Everything is computed client-side. Each page fetches the full list and filters,
sorts, counts, and derives in the browser. There is no query API — listProcesses()
returns every process and always has.
Fine at hundreds of runs. At tens of thousands, every one of these screens ships the entire collection to the browser on load. See storage.
Permission-aware, not permission-enforced. Cards render — and nav items hide when
permissions are missing, but the gating that matters happens in the API. Hiding a link
does not block the route.
0.
Details/processes shows them rejected.
Details