Run status is read from persisted state, on two routes and one envelope
The live picture of a run is whatever has been persisted for it, not what some in-memory tracker happens to remember. A poll therefore answers the same value to every caller, including one served by a process that has just started.
The rule
- A run's status is published by two reads: the full pipeline document and a lightweight status document.
- Both answer the standard
{success: true, data}envelope, publish the persisted lifecycle value verbatim asdata.status, and answer404with{success: false, error}for a run that does not exist and403for one the caller may not view. - The full document adds
node_statuses,jobs,job_status_summaryandexecution_dataalongsideid,name,description,createdAt,lastExecuted,executionCountandtimestamp; the lightweight document carriesid,status,createdAt,lastExecuted,pendingInterruptandpausedReasonand must not carry the jobs payload. - Both read persisted state only, so a status written outside the request path is what the next poll returns.
What it means
Two different reads publish the same live picture of a run because both are
windows onto the same persisted record, never an in-memory tracker that
could disagree with it from one process to the next, or lag behind a status
that was just written. The two reads deliberately diverge in only one
respect: the lightweight document must not carry the jobs payload at all,
because it exists for a caller polling too fast to justify the weight of the
full one. Where the run cannot be found at all, the answer is 404 naming
the id; where it exists but the caller may not view it, that is 403 —
never a payload with some of its fields quietly blank instead.
Example
The same distinction — missing versus denied — holds on both doors.
GET /api/flowdrop/pipeline/{pipeline_id}
{"success": false, "error": "Pipeline with ID 99999 does not exist."}GET /api/flowdrop/pipeline/{pipeline_id}/status
{"success": false, "error": "Access denied"}