@conduction/nextcloud-vue 2.121.0 → 2.123.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js +1 -0
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js.map +1 -1
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js.map +1 -1
- package/dist/esm/components/CnAttentionFlagWidget/CnAttentionFlagWidget.vue.js +1 -1
- package/dist/esm/components/CnAttentionFlagWidget/CnAttentionFlagWidget.vue2.js +18 -4
- package/dist/esm/components/CnAttentionFlagWidget/CnAttentionFlagWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnAttentionFlagWidget/CnAttentionFlagWidget.vue3.js +63 -32
- package/dist/esm/components/CnAttentionFlagWidget/CnAttentionFlagWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue.js +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +35 -0
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +11 -5
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue.js +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js +13 -0
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js +37 -5
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue.js +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js +40 -0
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js +71 -65
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js.map +1 -1
- package/dist/esm/components/CnFlowDetail/CnFlowDetail.vue.js +1 -1
- package/dist/esm/components/CnFlowDetail/CnFlowDetail.vue2.js +20 -0
- package/dist/esm/components/CnFlowDetail/CnFlowDetail.vue2.js.map +1 -1
- package/dist/esm/components/CnFlowDetail/CnFlowDetail.vue3.js +2 -1
- package/dist/esm/components/CnFlowDetail/CnFlowDetail.vue3.js.map +1 -1
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue.js +1 -1
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue2.js +2 -0
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue2.js.map +1 -1
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue3.js +49 -44
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue3.js.map +1 -1
- package/dist/esm/components/CnFlowsPage/CnFlowEditorPage.vue2.js +10 -0
- package/dist/esm/components/CnFlowsPage/CnFlowEditorPage.vue2.js.map +1 -1
- package/dist/esm/components/CnFlowsPage/CnFlowEditorPage.vue3.js +2 -1
- package/dist/esm/components/CnFlowsPage/CnFlowEditorPage.vue3.js.map +1 -1
- package/dist/esm/components/CnGraphCanvas/CnGraphCanvas.vue2.js +31 -0
- package/dist/esm/components/CnGraphCanvas/CnGraphCanvas.vue2.js.map +1 -1
- package/dist/esm/components/CnGraphCanvas/CnGraphCanvas.vue3.js +4 -3
- package/dist/esm/components/CnGraphCanvas/CnGraphCanvas.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +34 -2
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue3.js +1 -0
- package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue.js +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js +2 -0
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js +2 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js.map +1 -1
- package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue.js +1 -1
- package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue2.js +31 -1
- package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue3.js +14 -4
- package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue3.js.map +1 -1
- package/dist/esm/composables/flowGraphLayout.js +36 -7
- package/dist/esm/composables/flowGraphLayout.js.map +1 -1
- package/dist/esm/composables/useFlowStore.js +7 -3
- package/dist/esm/composables/useFlowStore.js.map +1 -1
- package/dist/esm/l10n/en.json.js +3 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +3 -1
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/library-style.js +1 -1
- package/dist/esm/nextcloud-vue.css +670 -316
- package/dist/esm/utils/manifestTranslate.js +12 -3
- package/dist/esm/utils/manifestTranslate.js.map +1 -1
- package/dist/esm/utils/routeFilters.js +3 -3
- package/dist/esm/utils/routeFilters.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +1218 -847
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +670 -316
- package/l10n/en.json +3 -1
- package/l10n/nl.json +3 -1
- package/package.json +1 -1
- package/src/components/CnAppRoot/CnAppRoot.vue +1 -0
- package/src/components/CnAttentionFlagWidget/CnAttentionFlagWidget.vue +50 -5
- package/src/components/CnChartWidget/CnChartWidget.vue +10 -8
- package/src/components/CnDetailPage/CnDetailPage.md +10 -0
- package/src/components/CnDetailPage/CnDetailPage.vue +42 -1
- package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +39 -0
- package/src/components/CnFilesBrowser/CnFilesBrowser.vue +95 -37
- package/src/components/CnFlowDetail/CnFlowDetail.vue +21 -0
- package/src/components/CnFlowsPage/CnFlowBoard.vue +35 -18
- package/src/components/CnFlowsPage/CnFlowEditorPage.vue +11 -0
- package/src/components/CnGraphCanvas/CnGraphCanvas.vue +34 -2
- package/src/components/CnIndexPage/CnIndexPage.vue +34 -2
- package/src/components/CnIndexSidebar/CnIndexSidebar.vue +1 -0
- package/src/components/CnObjectSidebar/CnFilesTab.vue +3 -0
- package/src/components/CnSectionsWidget/CnSectionsWidget.vue +53 -2
- package/src/composables/flowGraphLayout.js +35 -6
- package/src/composables/useFlowStore.js +7 -3
- package/src/css/detail-page.css +6 -0
- package/src/css/look-board-detail.css +53 -6
- package/src/css/look-board-index.css +151 -12
- package/src/css/look-board.css +116 -4
- package/src/utils/manifestTranslate.js +12 -3
- package/src/utils/routeFilters.js +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFlowStore.js","sources":["../../../src/composables/useFlowStore.js"],"sourcesContent":["// SPDX-License-Identifier: EUPL-1.2\n// Copyright (C) 2026 Conduction B.V.\n//\n// Shared state for the flow editor.\n//\n// The canvas (CnFlowDetail) and the controls (CnFlowSidebar) render in two\n// different places — the page body and Nextcloud's app sidebar — so they cannot\n// pass props to one another. The flow being edited lives here instead.\n//\n// Ported from hermiq's `graphEditor` store, which was the fleet's only flow\n// editor. Two things changed in the port:\n//\n// 1. Persistence is OpenRegister's ONE flow store (`/api/flows`), not an app's\n// own register. That is the whole point of the unification: hermiq kept\n// flows as `agentflow` objects, so every app that wanted flows needed its\n// own register, its own resolver and — in practice — its own executor.\n// 2. Node types are the catalogue's ids, VERBATIM. hermiq's builder fed its\n// palette from the catalogue (namespaced: `openregister.set-fields`,\n// `hermiq.agent-step`) while its config panes and its executor matched\n// BARE ids (`set-fields`, `agent-step`). Every node placed from the palette\n// therefore had no config pane and was skipped at run time — silently, with\n// the run reporting success. Nothing here may reintroduce a second\n// vocabulary.\n\nimport axios from '@nextcloud/axios'\nimport { translate as t } from '@nextcloud/l10n'\nimport { generateUrl } from '@nextcloud/router'\nimport { defineStore } from 'pinia'\nimport { layoutFlowNodes, needsFullLayout, placeLooseNodes } from './flowGraphLayout.js'\nimport { DEFAULT_EDGE_LINE_TYPE } from './useFlowEdgeStyles.js'\n\n/**\n * A blank flow definition.\n *\n * @return {object} The empty flow.\n */\n/**\n * The fields that make up the pinned DEFINITION of a flow.\n *\n * Kept in step with `FlowDefinitionPin::PINNED_KEYS` on the server: these four\n * are what a version's hash is taken over, so these four are what a published\n * version refuses to have changed.\n *\n * @type {string[]}\n */\nconst GRAPH_FIELDS = ['nodes', 'edges', 'limits', 'executionMode']\n\n/**\n * The run statuses the engine treats as \"still going\".\n *\n * Mirrors `FlowRun::ACTIVE` on the server (`queued`, `running`, `suspended`);\n * everything else (`completed`, `stopped`, `failed`, `dead_letter`) is\n * terminal. The watcher polls while a run is in this set and stops by itself\n * the moment it leaves it.\n *\n * @type {string[]}\n */\nexport const FLOW_RUN_ACTIVE_STATUSES = ['queued', 'running', 'suspended']\n\n/**\n * How often the watched run is polled, and the floor under a caller-supplied\n * interval.\n *\n * 3s because the editor's Run is interactive — a person is looking — so the\n * dashboard widget's 15s feels dead; floored at 2s because the engine writes\n * the log once per worker pass, so polling faster multiplies requests for no\n * extra information.\n */\nconst WATCH_INTERVAL_DEFAULT_MS = 3000\nconst WATCH_INTERVAL_FLOOR_MS = 2000\n\nfunction emptyFlow() {\n\treturn {\n\t\tname: '',\n\t\tdescription: '',\n\t\tnotes: '',\n\t\tapp: 'openregister',\n\t\ttriggerRegister: '',\n\t\ttriggerSchema: '',\n\t\ttrigger: 'object.updated',\n\t\tcron: '',\n\t\texecutionMode: 'async',\n\t\tenabled: false,\n\t\tnodes: [],\n\t\tedges: [],\n\t\tlimits: {},\n\t\tretentionDays: null,\n\t\tauditEnabled: null,\n\t\toversightEnabled: null,\n\n\t\t// A new flow is a DRAFT. Nothing runs it until it is published, which\n\t\t// is the point: an author builds a graph over several sittings and a\n\t\t// half-wired process must not be firing on object writes in between.\n\t\tversion: 1,\n\t\tlifecycleStatus: 'draft',\n\t}\n}\n\nexport const useFlowStore = defineStore('cnFlow', {\n\tstate: () => ({\n\t\tflow: emptyFlow(),\n\t\tflows: [],\n\n\t\t// Snapshots of `flow`, oldest first, for Ctrl+Z.\n\t\t//\n\t\t// A canvas is direct manipulation: a mis-drag or a mis-aimed Delete\n\t\t// destroys work with no dialog in between, and until this existed the\n\t\t// only way back was to reload and lose everything since the last save.\n\t\t// The stack is capped — see pushUndo() — because a flow document is\n\t\t// held whole in each entry.\n\t\tundoStack: [],\n\t\tselectedNodeId: null,\n\t\tpaletteDragType: null,\n\n\t\t// The node whose edit dialog is open, or null. Lives here because the\n\t\t// dialog is hosted by the canvas while it is opened from the sidebar,\n\t\t// a node double-click, or a consumer.\n\t\teditingNodeId: null,\n\n\t\t// The CONNECTION whose edit dialog is open, as `{source, target}`, or\n\t\t// null.\n\t\t//\n\t\t// ⚠️ NOT AN ID. `canvasEdges` expands one stored edge into several drawn\n\t\t// lines — `{from: 'a', to: ['b', 'c']}` is two lines — so a line's id is\n\t\t// synthesised per render and means nothing to the document. The endpoint\n\t\t// pair is the only thing that identifies a line in both worlds, and it\n\t\t// is what every edge action below is keyed on.\n\t\teditingEdge: null,\n\n\t\t// The label and router copied off a line, for pasting onto another. A\n\t\t// line has no meaningful duplicate — two identical `from`/`to` records\n\t\t// draw on top of each other and the engine dedupes them — so Copy on a\n\t\t// connection copies its PRESENTATION, which is the part that is actually\n\t\t// worth repeating across a graph.\n\t\tedgeStyleClipboard: null,\n\n\t\t// Whether the controls sidebar is shown. Lives here because the\n\t\t// re-open affordance sits on the canvas toolbar, in the other half of\n\t\t// the tree.\n\t\tsidebarOpen: true,\n\n\t\t// Every version of the open flow, newest first.\n\t\tversions: [],\n\n\t\t// The server's last lifecycle refusal, as `{reason, lifecycleStatus}`.\n\t\t//\n\t\t// 🔑 KEPT AS THE SERVER'S FIELDS, not as a rendered sentence. \"this\n\t\t// version is published, create a draft\" and \"this flow has no published\n\t\t// version, publish one\" want opposite buttons, and choosing between\n\t\t// them by matching on message text is how a UI offers the wrong one.\n\t\tlifecycleRefusal: null,\n\n\t\t// Whether a lifecycle transition is in flight.\n\t\ttransitioning: false,\n\n\t\t// What publishing WOULD do, as the server answered it: the next\n\t\t// semantic version, and when major, what the publish takes away.\n\t\t//\n\t\t// 🔑 THE SERVER'S ANSWER, NOT A SECOND OPINION. Deriving \"this looks\n\t\t// breaking\" in the client would be a second implementation of the rule,\n\t\t// and the first time the two disagree the author learns to believe\n\t\t// neither.\n\t\tpublishPreview: null,\n\n\t\t// Whether that preview is being fetched.\n\t\tpreviewingPublish: false,\n\n\t\t// The server's refusal of an explicit bump, as a sentence naming what\n\t\t// was removed. Separate from `lifecycleRefusal`: the flow's state is\n\t\t// fine, the REQUEST is what was wrong.\n\t\tversionBumpRefusal: null,\n\n\t\t// The node types the engine can actually execute. The catalogue is\n\t\t// AUTHORITATIVE: a builder that invents its own ids produces flows the\n\t\t// engine cannot run, which is exactly the defect this replaces.\n\t\tnodeCatalog: [],\n\t\teventCatalog: [],\n\n\t\t// Whether the catalogue request is still in flight. Without this flag\n\t\t// the palette cannot tell \"loading\" from \"failed\": both are an empty\n\t\t// list, and the sidebar showed \"Could not read the flow engine's node\n\t\t// types\" on every fresh /flows/new while the request was mid-air.\n\t\tcatalogLoading: false,\n\n\t\t// Per flow id: `{ lastRun, runsSince }` from `GET /api/flow-runs/summary`,\n\t\t// the read behind a flow list's last-run and runs-this-week columns.\n\t\trunSummary: {},\n\t\t// The runs of every listed flow since `runSummarySince`, for a\n\t\t// \"runs this week\" list. Separate from `runs`, which belongs to the\n\t\t// flow open in the editor.\n\t\trecentRuns: [],\n\t\trecentRunsLoading: false,\n\n\t\t// The runs of the flow being edited, and the per-node steps of the run\n\t\t// currently being inspected.\n\t\truns: [],\n\t\tsteps: [],\n\t\t// What the inspected run TOUCHED, grouped by node. Distinct from\n\t\t// `steps`, which is what it did: a step that wrote nothing still has a\n\t\t// step row, and an object written by an app the node called into has no\n\t\t// step of its own.\n\t\trunObjects: [],\n\t\t// The tasks THIS RUN raised, from `GET /api/flow-tasks?runUuid={uuid}`.\n\t\t//\n\t\t// The parameter ANCHORS the read rather than filtering it: with it\n\t\t// present the server ignores `scope`, so these are the run's tasks and\n\t\t// not the reader's inbox. Visibility still applies on top, so a caller\n\t\t// who is neither the run's requester nor an admin can see fewer rows\n\t\t// than the run has. That is correct, and nothing here works around it.\n\t\trunTasks: [],\n\t\tinspectedRunUuid: null,\n\n\t\t// THE INSPECTED RUN'S OWN RECORD, as the server answered it.\n\t\t//\n\t\t// `runs` is the flow's run history and it is capped at 25, so a run\n\t\t// reached by `?run=` need not be in it at all. Reading the header from\n\t\t// that list alone left a deep-linked run with no status, no time and no\n\t\t// error, which reads as a run that recorded nothing.\n\t\t//\n\t\t// It also carries what `GET /flow-runs/{uuid}/objects` cannot: the\n\t\t// objects the run is ABOUT (`subjects`) and the ones it is holding at a\n\t\t// place (`placeItems`). That endpoint reports audited CHANGES, so a run\n\t\t// that waited on a locked object and failed lists nothing there while\n\t\t// its own error names that object.\n\t\trunDetail: null,\n\n\t\t// THE GRAPH AS IT RAN, not the graph as it is now.\n\t\t//\n\t\t// A run records the `flowVersion` it executed, and a flow's graph moves\n\t\t// on: steps are added, renamed and deleted. Replaying an old run over\n\t\t// today's canvas paints badges onto nodes that were not there when it\n\t\t// ran and silently drops the ones that have since been deleted — the\n\t\t// `run-skipped` warning in CnFlowDetail exists solely to apologise for\n\t\t// that. So inspecting a run loads that version's stored graph and shows\n\t\t// it, and the reader is looking at what actually executed.\n\t\t//\n\t\t// `viewingVersion` is the version number on the canvas, or null for the\n\t\t// live graph. `liveGraph` is the graph that was displaced, kept so\n\t\t// closing the run restores it EXACTLY rather than refetching and hoping.\n\t\t// `runGraphNotice` is why the snapshot is NOT on the canvas when a run\n\t\t// is open, as `{ version, reason }`. There are two reasons and they are\n\t\t// not interchangeable: `unreadable` is a version row that could not be\n\t\t// fetched, and `unsaved-edits` is a canvas we refused to displace. Both\n\t\t// end with the replay drawn over the live graph, so without this the\n\t\t// reader cannot tell which graph they are looking at, and the answer\n\t\t// differs from the one the `viewingVersion` banner would have given.\n\t\tviewingVersion: null,\n\t\tliveGraph: null,\n\t\trunGraphNotice: null,\n\n\t\t// The run being WATCHED live: the one `run()` just queued, polled while\n\t\t// its status is non-terminal. The store exposes FACTS about it — the\n\t\t// run, its ordered steps, which of them are new since the last poll —\n\t\t// and animates nothing: the animation timeline lives in CnFlowDetail,\n\t\t// the only place that knows what a hop looks like. Splitting it this\n\t\t// way keeps the store testable without a clock.\n\t\twatchedRunUuid: null,\n\t\twatchedRun: null,\n\n\t\t// The watched run's log so far, in the engine's order. WITHIN ONE RUN\n\t\t// THE LOG ONLY GROWS — the engine appends per worker pass, and a\n\t\t// resumed pass appends after the `suspended` entry — so entries are\n\t\t// appended by index and an already-exposed step is never replaced or\n\t\t// replayed.\n\t\twatchedSteps: [],\n\n\t\t// Where the latest poll's NEW entries start in `watchedSteps`. The\n\t\t// index diff is exact because the log only grows; a consumer reads\n\t\t// `newWatchedSteps` to learn what arrived without replaying the rest.\n\t\twatchedNewFrom: 0,\n\n\t\t// Whether the poll loop is live. Stays true while the tab is hidden —\n\t\t// the timer is paused, not the watch — and turns false on a terminal\n\t\t// status, a re-watch, or teardown.\n\t\twatching: false,\n\n\t\t// A replay request for the INSPECTED run, as a monotonic token. The\n\t\t// sidebar raises it (`requestReplay()`), the canvas half watches it and\n\t\t// plays `steps` through its animator. A token rather than a flag so\n\t\t// replaying the same run twice in a row is two requests.\n\t\treplayUuid: null,\n\t\treplayToken: 0,\n\n\t\t// The flow LIST request, and nothing else. Read the comment below before\n\t\t// reaching for it as \"the editor is loading\": it is not.\n\t\tloading: false,\n\t\tsaving: false,\n\t\trunning: false,\n\t\tchecking: false,\n\n\t\t// 🔴 WHAT `loading` DOES NOT COVER, AND WHY A SECOND FLAG EXISTS.\n\t\t//\n\t\t// `loading` is set around `GET /api/flows` alone. The editor's arrival is\n\t\t// up to three requests deep: the list, then the run named by `?run=`,\n\t\t// then the stored graph that run executed. The canvas rendered\n\t\t// \"No steps yet\" through all of it, because `nodes.length === 0` is true\n\t\t// for a flow that has not arrived yet.\n\t\t//\n\t\t// An empty state that means \"still fetching\" is indistinguishable from\n\t\t// one that means \"this flow has no steps\", and only the second is an\n\t\t// answer. So `bootstrapping` spans the WHOLE arrival: the surface about\n\t\t// to make those requests raises it before the first one, and lowers it\n\t\t// when the last has settled.\n\t\tbootstrapping: false,\n\n\t\t// The run the URL named, from before it has been fetched.\n\t\t//\n\t\t// `inspectedRunUuid` is only set once `inspectRun()` runs, and that is\n\t\t// behind the flow load, so a visitor arriving on `/flows/x?run=y` saw\n\t\t// the full flow editor first and the run view a moment later, complete\n\t\t// with Add a step, Save and a sidebar telling them to save the flow.\n\t\t// The URL had already said a run was being viewed, so this records that\n\t\t// fact synchronously and `inRunView` reads both.\n\t\topeningRunUuid: null,\n\n\t\t// The engine's verdict on the unsaved canvas, from `check()`. Cleared\n\t\t// by any edit that could change it, so a stale \"looks runnable\" never\n\t\t// outlives the graph it described.\n\t\tcheckResult: null,\n\n\t\tdirty: false,\n\t\terror: null,\n\t\t/**\n\t\t * The flow id that could not be resolved, or null.\n\t\t *\n\t\t * Distinct from `error`, which is a failed REQUEST. A flow that resolves\n\t\t * to nothing is a successful request with an empty answer, and the canvas\n\t\t * must be able to tell a reader that rather than rendering an empty grid\n\t\t * that looks like a flow with no steps.\n\t\t */\n\t\tnotFound: null,\n\t}),\n\n\tgetters: {\n\t\tnodes: (state) => state.flow.nodes || [],\n\t\tedges: (state) => state.flow.edges || [],\n\n\t\t/**\n\t\t * Whether this flow runs inline rather than through the worker.\n\t\t *\n\t\t * The engine's own vocabulary is `sync` / `async` on the flow, and the\n\t\t * default is async — so anything the API has not told us about, or has\n\t\t * not set, queues. Reading it here rather than at the call site keeps\n\t\t * the one place that knows the vocabulary.\n\t\t *\n\t\t * @param {object} state The store state.\n\t\t * @return {boolean} True when a run should be executed immediately.\n\t\t */\n\t\trunsSynchronously: (state) => String(state.flow.executionMode || '').toLowerCase() === 'sync',\n\n\t\t/**\n\t\t * @param {object} state The store state.\n\t\t * @return {string} The open flow's lifecycle status.\n\t\t */\n\t\tlifecycleStatus: (state) => state.flow.lifecycleStatus || 'draft',\n\n\t\t/**\n\t\t * @param {object} state The store state.\n\t\t * @return {number} The open flow's version number.\n\t\t */\n\t\tflowVersion: (state) => Number(state.flow.version || 1),\n\n\t\t/**\n\t\t * What the version pill says: the semantic version where the engine\n\t\t * has derived one, the ordinal where it has not.\n\t\t *\n\t\t * A flow that has never been published has no semantic version, and a\n\t\t * draft has none either — it has not been compared with anything yet.\n\t\t * Showing `v0.0.0` there would be a claim; showing the ordinal is the\n\t\t * truth the flow actually carries.\n\t\t *\n\t\t * @param {object} state The store state.\n\t\t * @return {string} The label, without a leading `v`.\n\t\t */\n\t\tflowVersionLabel: (state) => {\n\t\t\tconst semver = String(state.flow.semver || '').trim()\n\n\t\t\treturn (semver === '') ? String(Number(state.flow.version || 1)) : semver\n\t\t},\n\n\t\t/**\n\t\t * @param {object} state The store state.\n\t\t * @return {boolean} Whether the open flow is a draft.\n\t\t */\n\t\tisDraft: (state) => (state.flow.lifecycleStatus || 'draft') === 'draft',\n\n\t\t/**\n\t\t * @param {object} state The store state.\n\t\t * @return {boolean} Whether the open flow is published.\n\t\t */\n\t\tisPublished: (state) => state.flow.lifecycleStatus === 'published',\n\n\t\t/**\n\t\t * Whether the GRAPH may not be edited.\n\t\t *\n\t\t * 🔴 THE GRAPH, NOT THE FLOW. A published version's nodes and edges are\n\t\t * immutable, but its name, description and enabled flag are not —\n\t\t * renaming a live process or switching it off are not changes to the\n\t\t * process. The server draws the line in exactly the same place, so an\n\t\t * editor that locked everything would refuse edits the API accepts.\n\t\t *\n\t\t * 🔴 A VERSION SNAPSHOT IS LOCKED TOO, AND THIS IS NOT COSMETIC.\n\t\t *\n\t\t * `viewingVersion` means the canvas holds a HISTORIC graph loaded for a\n\t\t * run replay, while `flow.id` still names the live flow. `save()` picks\n\t\t * PUT over POST from `flow.id`, so a single edit-and-save on a snapshot\n\t\t * would overwrite the current flow with an old graph — the same class of\n\t\t * loss the `id` watcher in CnFlowDetail was written to prevent, reached\n\t\t * by a different door. Reusing the existing lock rather than inventing a\n\t\t * read-only mode means every caller that already respects `graphLocked`\n\t\t * — `pushUndo()` and everything gated behind it — is correct here for\n\t\t * free, and a new call site cannot forget the snapshot case.\n\t\t *\n\t\t * @param {object} state The store state.\n\t\t * @return {boolean} Whether graph edits are locked.\n\t\t */\n\t\tgraphLocked: (state) => state.viewingVersion !== null\n\t\t\t|| ['published', 'deprecated'].includes(state.flow.lifecycleStatus),\n\n\t\t/**\n\t\t * Whether the surfaces are showing a RUN rather than the flow.\n\t\t *\n\t\t * 🔑 TWO SOURCES, AND THE EARLY ONE IS THE POINT. `inspectedRunUuid` is\n\t\t * the run that has been read; `openingRunUuid` is the run the URL named,\n\t\t * known before anything is fetched. Reading only the first meant the\n\t\t * editor spent the whole load in flow-edit mode with the address bar\n\t\t * already saying otherwise, so the reader was offered Add a step, Save\n\t\t * and Run on a page that was about to become read-only.\n\t\t *\n\t\t * @param {object} state The store state.\n\t\t * @return {boolean} True while a run is open or being opened.\n\t\t */\n\t\tinRunView: (state) => Boolean(state.inspectedRunUuid) || state.openingRunUuid !== null,\n\n\t\t/**\n\t\t * Whether the canvas is still waiting for the graph it is going to show.\n\t\t *\n\t\t * The one flag a canvas should ask, rather than assembling it from\n\t\t * `loading` plus two run flags at every call site: any of the three\n\t\t * requests behind the first paint being in the air means the graph on\n\t\t * screen is not yet an answer.\n\t\t *\n\t\t * @param {object} state The store state.\n\t\t * @return {boolean} True while the graph is still being fetched.\n\t\t */\n\t\tcanvasLoading: (state) => state.bootstrapping === true || state.openingRunUuid !== null,\n\n\t\t/**\n\t\t * Whether there is anything to undo. Drives the toolbar's disabled state.\n\t\t *\n\t\t * @param {object} state The store state.\n\t\t * @return {boolean} True when the stack holds at least one snapshot.\n\t\t */\n\t\tcanUndo: (state) => state.undoStack.length > 0,\n\n\t\tselectedNode: (state) => {\n\t\t\tif (state.selectedNodeId === null) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\treturn (state.flow.nodes || []).find((n) => n.id === state.selectedNodeId) || null\n\t\t},\n\n\t\t/**\n\t\t * The node whose edit dialog is open, or null.\n\t\t *\n\t\t * @param {object} state The store state.\n\t\t * @return {object|null} The node.\n\t\t */\n\t\teditingNode: (state) => {\n\t\t\tif (state.editingNodeId === null) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\treturn (state.flow.nodes || []).find((n) => n.id === state.editingNodeId) || null\n\t\t},\n\n\t\t/**\n\t\t * The catalogue entry for a node type, or null when the engine does not\n\t\t * know it.\n\t\t *\n\t\t * A null here is meaningful and must be SHOWN, not hidden: it means the\n\t\t * flow carries a node the engine cannot resolve, which will fail its\n\t\t * step at run time.\n\t\t *\n\t\t * @param {object} state The store state.\n\t\t * @return {(type: string) => object|null} The catalogue entry, or null when the engine does not know the type.\n\t\t */\n\t\tcatalogEntry: (state) => (type) => {\n\t\t\treturn state.nodeCatalog.find((entry) => (\n\t\t\t\tentry.id === type || (entry.aliases || []).includes(type)\n\t\t\t)) || null\n\t\t},\n\n\t\t/**\n\t\t * A node type's role — `trigger`, `step` or `end` — from the catalogue.\n\t\t *\n\t\t * Falls back to the id's naming convention only while the catalogue has\n\t\t * not loaded, so the canvas is not colourless during the first paint.\n\t\t *\n\t\t * @return {(type: string) => 'trigger'|'step'|'end'} The role of a node type.\n\t\t */\n\t\troleOfNodeType() {\n\t\t\treturn (type) => {\n\t\t\t\tconst entry = this.catalogEntry(type)\n\t\t\t\tif (entry?.role) {\n\t\t\t\t\treturn entry.role\n\t\t\t\t}\n\n\t\t\t\tconst id = String(type || '')\n\t\t\t\tif (id.includes('.trigger-')) {\n\t\t\t\t\treturn 'trigger'\n\t\t\t\t}\n\t\t\t\tif (id.endsWith('.end') || id.endsWith('.stop')) {\n\t\t\t\t\treturn 'end'\n\t\t\t\t}\n\n\t\t\t\treturn 'step'\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * The edges as the canvas draws them: one line per (source, target)\n\t\t * pair, whatever dialect the stored flow speaks.\n\t\t *\n\t\t * This store writes `{from, to}` — the ONLY dialect the engine reads —\n\t\t * but it must still DRAW `{source, target}`, which older documents and\n\t\t * hermiq's flows carry. Each endpoint\n\t\t * may be a LIST (several `from` = join, several `to` = split). Handing\n\t\t * `flow.edges` to the canvas raw therefore rendered every one of those\n\t\t * flows as unconnected cards: real graphs, silently drawn wrong.\n\t\t *\n\t\t * @param {object} state The store state.\n\t\t * @return {Array<object>} Drawable `{id, source, target, edge}` lines.\n\t\t */\n\t\tcanvasEdges: (state) => {\n\t\t\tconst toList = (value) => {\n\t\t\t\tif (Array.isArray(value)) {\n\t\t\t\t\treturn value.filter((v) => v !== null && v !== undefined && v !== '')\n\t\t\t\t}\n\n\t\t\t\treturn (value === null || value === undefined || value === '') ? [] : [value]\n\t\t\t}\n\n\t\t\tconst lines = []\n\t\t\tfor (const [index, edge] of (state.flow.edges || []).entries()) {\n\t\t\t\tconst sources = toList(edge.source ?? edge.from)\n\t\t\t\tconst targets = toList(edge.target ?? edge.to)\n\t\t\t\tconst edgeId = edge.id || `edge-${index}`\n\n\t\t\t\tfor (const source of sources) {\n\t\t\t\t\tfor (const target of targets) {\n\t\t\t\t\t\t// The line id must not be the edge id: a split renders\n\t\t\t\t\t\t// one edge as several lines, and v-for keys collide.\n\t\t\t\t\t\tlines.push({\n\t\t\t\t\t\t\tid: `${edgeId}:${source}:${target}`,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\ttarget,\n\n\t\t\t\t\t\t\t// LET VUE FLOW ROUTE THE LINE.\n\t\t\t\t\t\t\t//\n\t\t\t\t\t\t\t// These carried no `type`, so every line fell back\n\t\t\t\t\t\t\t// to Vue Flow's default bezier — which crosses\n\t\t\t\t\t\t\t// nodes and doubles back on itself as soon as a\n\t\t\t\t\t\t\t// graph stops being a straight chain. That read as\n\t\t\t\t\t\t\t// \"our lines are disorderly\", and the instinct was\n\t\t\t\t\t\t\t// to lay the graph out ourselves to compensate.\n\t\t\t\t\t\t\t//\n\t\t\t\t\t\t\t// `smoothstep` is orthogonal routing with rounded\n\t\t\t\t\t\t\t// corners: it is what the hand-drawn canvas was\n\t\t\t\t\t\t\t// imitating, and the flow-builder's own dead `#edge`\n\t\t\t\t\t\t\t// slot described the goal as \"orthogonal routing\n\t\t\t\t\t\t\t// plus an explicit arrowhead\". Both are Vue Flow\n\t\t\t\t\t\t\t// options we had simply never set.\n\t\t\t\t\t\t\t//\n\t\t\t\t\t\t\t// PER EDGE, and the document wins. `edge.lineType`\n\t\t\t\t\t\t\t// is stored on the connection, so a single awkward\n\t\t\t\t\t\t\t// line can be switched to `step`, `straight` or\n\t\t\t\t\t\t\t// `default` without moving a node — the seam an\n\t\t\t\t\t\t\t// edge-level control hangs off.\n\t\t\t\t\t\t\t//\n\t\t\t\t\t\t\t// ⚠️ THE ROUTER TRAVELS IN `data`, NOT IN `type`.\n\t\t\t\t\t\t\t// It sat in `type` when the router was the only\n\t\t\t\t\t\t\t// thing an edge carried, and that quietly ruled out\n\t\t\t\t\t\t\t// everything else: Vue Flow reads `type` to choose\n\t\t\t\t\t\t\t// the COMPONENT that draws the line, so naming a\n\t\t\t\t\t\t\t// router there means the built-in edge answers and\n\t\t\t\t\t\t\t// no label, marker control or payload affordance\n\t\t\t\t\t\t\t// can ever be attached. `default` selects\n\t\t\t\t\t\t\t// CnFlowEdge, which reads the router back out of\n\t\t\t\t\t\t\t// `data`. Same distinction the node side already\n\t\t\t\t\t\t\t// records — `type` is a component, and a domain\n\t\t\t\t\t\t\t// value put there is a component that does not\n\t\t\t\t\t\t\t// exist.\n\t\t\t\t\t\t\ttype: 'default',\n\n\t\t\t\t\t\t\t// ⚠️ SIZED, BECAUSE THE DEFAULT ARROWHEAD WAS DRAWN\n\t\t\t\t\t\t\t// UNDERNEATH THE PORT HANDLE.\n\t\t\t\t\t\t\t//\n\t\t\t\t\t\t\t// `'arrowclosed'` on its own renders a 12.5px arrow\n\t\t\t\t\t\t\t// at the path's end — which is exactly where the\n\t\t\t\t\t\t\t// target node's handle sits, and that handle is an\n\t\t\t\t\t\t\t// 18px filled circle in a layer Vue Flow paints\n\t\t\t\t\t\t\t// ABOVE the edges. So the arrow was there the whole\n\t\t\t\t\t\t\t// time, measurably, and no user could see it: the\n\t\t\t\t\t\t\t// canvas read as a set of undirected lines.\n\t\t\t\t\t\t\t//\n\t\t\t\t\t\t\t// 22px is chosen against the handle, not for looks\n\t\t\t\t\t\t\t// — the arrow has to extend beyond it to read as an\n\t\t\t\t\t\t\t// arrow at all. Colour is deliberately NOT set here:\n\t\t\t\t\t\t\t// Vue Flow writes it as an inline style on the\n\t\t\t\t\t\t\t// polyline, so it is themed in CSS instead (see\n\t\t\t\t\t\t\t// `.vue-flow__arrowhead` in CnGraphCanvas) and\n\t\t\t\t\t\t\t// follows dark mode.\n\t\t\t\t\t\t\tmarkerEnd: edge.markerEnd || { type: 'arrowclosed', width: 22, height: 22 },\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\tlineType: edge.lineType || DEFAULT_EDGE_LINE_TYPE,\n\t\t\t\t\t\t\t\tlabelT: edge.labelT,\n\t\t\t\t\t\t\t\tlabel: edge.title || edge.label || '',\n\t\t\t\t\t\t\t\tedge,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn lines\n\t\t},\n\n\t\t/**\n\t\t * The nodes a run enters through, decided the way the engine decides.\n\t\t *\n\t\t * @return {Array<string>} Their ids.\n\t\t */\n\t\tstartNodeIds() {\n\t\t\tconst nodes = this.nodes\n\t\t\tconst explicit = nodes.filter((n) => n.start === true || n.initial === true).map((n) => n.id)\n\t\t\tif (explicit.length) {\n\t\t\t\treturn explicit\n\t\t\t}\n\n\t\t\tconst targeted = new Set(this.canvasEdges.map((line) => line.target))\n\t\t\tconst sources = nodes.filter((n) => !targeted.has(n.id)).map((n) => n.id)\n\t\t\tif (sources.length) {\n\t\t\t\treturn sources\n\t\t\t}\n\n\t\t\treturn nodes.length ? [nodes[0].id] : []\n\t\t},\n\n\t\t/**\n\t\t * What stops this flow from ever finishing, by node ROLE.\n\t\t *\n\t\t * An empty flow reports nothing — there is no point telling the author\n\t\t * a blank canvas is incomplete.\n\t\t *\n\t\t * @return {{trigger: boolean, end: boolean}} The missing roles.\n\t\t */\n\t\tmissingEnds() {\n\t\t\tif (!this.nodes.length) {\n\t\t\t\treturn { trigger: false, end: false }\n\t\t\t}\n\n\t\t\tconst roles = this.nodes.map((n) => this.roleOfNodeType(n.type))\n\n\t\t\treturn {\n\t\t\t\ttrigger: !roles.includes('trigger'),\n\t\t\t\tend: !roles.includes('end'),\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Whether the watched run is still going.\n\t\t *\n\t\t * Read from the run's own `status` against the engine's non-terminal\n\t\t * set, never from `watching` — the poll loop can be paused (hidden\n\t\t * tab) or already stopped (terminal status seen) while the last\n\t\t * fetched state is what the canvas should keep painting.\n\t\t *\n\t\t * @param {object} state The store state.\n\t\t * @return {boolean} True while the run's status is non-terminal.\n\t\t */\n\t\twatchedRunActive: (state) => FLOW_RUN_ACTIVE_STATUSES.includes(state.watchedRun?.status),\n\n\t\t/**\n\t\t * The steps the latest poll ADDED, in log order.\n\t\t *\n\t\t * Index-diffed against what was already exposed, so a consumer can\n\t\t * tell new steps from ones it has already animated. Exact because the\n\t\t * log only grows within a run — see `watchedSteps`.\n\t\t *\n\t\t * @param {object} state The store state.\n\t\t * @return {Array<object>} The engine's log entries, as delivered.\n\t\t */\n\t\tnewWatchedSteps: (state) => state.watchedSteps.slice(state.watchedNewFrom),\n\n\t\t/**\n\t\t * The flow as the engine would run it.\n\t\t *\n\t\t * @param {object} state The store state.\n\t\t * @return {object} The runnable document.\n\t\t */\n\t\tflowForRun: (state) => ({\n\t\t\t...state.flow,\n\t\t\tnodes: state.flow.nodes || [],\n\t\t\tedges: state.flow.edges || [],\n\t\t}),\n\t},\n\n\tactions: {\n\t\t/**\n\t\t * Declare that the editor is opening, before the first request goes out.\n\t\t *\n\t\t * 🔴 CALLED FROM `created()`, NOT FROM `load()`, AND THAT IS THE FIX.\n\t\t * A flag raised inside `load()` is raised one tick too late: Vue renders\n\t\t * the component before `mounted()` runs, so the first paint had\n\t\t * `bootstrapping === false` with nothing loaded, the exact frame that\n\t\t * showed the editor's toolbar over \"No steps yet\". The surface that is\n\t\t * about to load says so before it renders.\n\t\t *\n\t\t * @param {string|null} runUuid The run the URL named, if it named one.\n\t\t * @return {void}\n\t\t */\n\t\tbeginBootstrap(runUuid = null) {\n\t\t\tthis.bootstrapping = true\n\t\t\tthis.openingRunUuid = runUuid || null\n\t\t},\n\n\t\t/**\n\t\t * The arrival has settled: the flow, and the run if there was one, are\n\t\t * as loaded as they are going to get.\n\t\t *\n\t\t * Lowers both flags. A failed load lands here too, via a `finally` at\n\t\t * the call site, because a canvas stuck saying \"loading\" forever is a\n\t\t * worse lie than the one this replaced.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tendBootstrap() {\n\t\t\tthis.bootstrapping = false\n\t\t\tthis.openingRunUuid = null\n\t\t},\n\n\t\t/**\n\t\t * Enter run view for a run that has not been read yet.\n\t\t *\n\t\t * Separate from `beginBootstrap` because a run can also be opened on a\n\t\t * flow that is already on the canvas: `?run=` changing on the same route\n\t\t * reuses the component, so there is no fresh arrival to hang it on.\n\t\t *\n\t\t * @param {string} runUuid The run being opened.\n\t\t * @return {void}\n\t\t */\n\t\tbeginOpeningRun(runUuid) {\n\t\t\tif (!runUuid) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.openingRunUuid = runUuid\n\t\t},\n\n\t\t/**\n\t\t * The run has been read, or the attempt failed. Either way it is no\n\t\t * longer being opened, and `inspectedRunUuid` is what holds run view\n\t\t * from here on.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tendOpeningRun() {\n\t\t\tthis.openingRunUuid = null\n\t\t},\n\n\t\t/**\n\t\t * Load the flows this surface is scoped to, plus both catalogues.\n\t\t *\n\t\t * @param {object} options Load options.\n\t\t * @param {string|null} options.app Restrict to one owning app id.\n\t\t * @param {string|null} options.id The flow to open, or 'new'.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync load({ app = null, id = null } = {}) {\n\t\t\t// A BLANK flow is initialised BEFORE the network, and this ordering\n\t\t\t// is the fix for #607 rather than a tidy-up.\n\t\t\t//\n\t\t\t// `emptyFlow()` has `name: ''`, and only `open('new')` supplies the\n\t\t\t// default name. `open()` used to run at the tail of this method,\n\t\t\t// behind `await GET /api/flows` — a flow LIST that starting a blank\n\t\t\t// flow does not need. Meanwhile the sidebar is already rendered and\n\t\t\t// Save already enabled, because `nodeCatalog` was populated by the\n\t\t\t// index page's own `load()` and this store is a singleton that\n\t\t\t// survives the route change.\n\t\t\t//\n\t\t\t// So there was a window in which the editor invited a Save of a flow\n\t\t\t// with no name, which `FlowController::create()` answers 400 \"A flow\n\t\t\t// needs a name.\" — measured at 9 of 10 attempts against a fresh\n\t\t\t// instance. The same late `open('new')` also reset `this.flow`, so a\n\t\t\t// step placed during the window was wiped, and a save landing after\n\t\t\t// it stored `nodes: []`.\n\t\t\t//\n\t\t\t// Nothing about a blank flow depends on the server, so it is set up\n\t\t\t// first, and NOT re-opened at the tail — re-opening is what threw the\n\t\t\t// user's work away.\n\t\t\t//\n\t\t\t// `id === 'new'` ONLY, never `id === null`. `save()` calls this\n\t\t\t// method as `load({ app })` to refresh the list, and a null id has\n\t\t\t// always meant \"reload the list, leave the open flow alone\". Treating\n\t\t\t// that as blank would reset the flow immediately after storing it,\n\t\t\t// discarding the id the server had just returned.\n\t\t\tconst isBlank = (id === 'new')\n\t\t\tif (isBlank === true) {\n\t\t\t\tthis.open('new', app)\n\t\t\t}\n\n\t\t\tthis.loading = true\n\t\t\tthis.error = null\n\t\t\ttry {\n\t\t\t\tconst params = app ? { app } : {}\n\t\t\t\tconst response = await axios.get(generateUrl('/apps/openregister/api/flows'), { params })\n\t\t\t\tthis.flows = response.data?.results || []\n\t\t\t} catch (error) {\n\t\t\t\t// Surfaced, not swallowed: an empty list with no trace of why is\n\t\t\t\t// indistinguishable from \"this instance has no flows\".\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not load flows', error)\n\t\t\t\tthis.flows = []\n\t\t\t\tthis.error = error\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\n\t\t\t// Both catalogues are kept OFF the critical path: the canvas is\n\t\t\t// usable while they resolve, and a failure costs the palette and the\n\t\t\t// trigger list rather than the editor.\n\t\t\tthis.loadNodeCatalog()\n\t\t\tthis.loadEventCatalog()\n\n\t\t\t// A blank flow was already opened above, before the network. Opening\n\t\t\t// it again here is what used to wipe a step the user had placed in\n\t\t\t// the meantime, so only a STORED flow is opened at this point — it\n\t\t\t// genuinely needs `this.flows`, which the request above just filled.\n\t\t\tif (id !== null && isBlank === false) {\n\t\t\t\t// 🔴 THE LIST IS NOT THE ONLY PLACE A FLOW CAN LIVE.\n\t\t\t\t//\n\t\t\t\t// `open()` resolves a flow by looking it up in `this.flows`, and\n\t\t\t\t// that list was just fetched scoped to ONE app. A flow belonging\n\t\t\t\t// to a different app is therefore absent, `open()` finds no match,\n\t\t\t\t// and — before this — returned silently, leaving the canvas\n\t\t\t\t// painted with whatever was there before: blank.\n\t\t\t\t//\n\t\t\t\t// That is not a hypothetical. A dossiq case ran eighteen flow runs\n\t\t\t\t// of a flow whose `app` is `openregister`; clicking any of them\n\t\t\t\t// opened `/flows/<id>` on dossiq's flow page, which loads\n\t\t\t\t// `?app=dossiq`, and the editor came up empty with no error.\n\t\t\t\t// Cross-app runs are ordinary — a case is driven by flows from\n\t\t\t\t// whichever app authored them.\n\t\t\t\t//\n\t\t\t\t// `GET /api/flows/{id}` resolves by uuid with no app filter, so\n\t\t\t\t// one request answers it. Only reached on a miss, so the common\n\t\t\t\t// case costs nothing.\n\t\t\t\tawait this.ensureFlowLoaded(id)\n\t\t\t\tthis.open(id, app)\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Make sure a flow is present in `this.flows` before `open()` looks for it.\n\t\t *\n\t\t * Fetches the single flow by uuid when the app-scoped list did not carry\n\t\t * it. A 404 is left alone: `open()` reports the not-found state, which is\n\t\t * the honest answer and the one the canvas can render.\n\t\t *\n\t\t * @param {string} id The flow uuid.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync ensureFlowLoaded(id) {\n\t\t\tif (!id || id === 'new') {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (this.flows.some((flow) => String(flow.id) === String(id))) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst response = await axios.get(generateUrl('/apps/openregister/api/flows/' + encodeURIComponent(id)))\n\t\t\t\tconst flow = response.data\n\t\t\t\tif (flow && flow.id) {\n\t\t\t\t\tthis.flows = [...this.flows, flow]\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\t// Surfaced, not swallowed — but not fatal either. `open()` sets\n\t\t\t\t// the not-found state right after this, and that is what the\n\t\t\t\t// canvas renders; throwing here would take out the whole page for\n\t\t\t\t// a flow that simply is not there any more.\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not resolve flow by id', id, error)\n\t\t\t}\n\t\t},\n\n\t\tasync loadNodeCatalog() {\n\t\t\tthis.catalogLoading = true\n\t\t\ttry {\n\t\t\t\tconst response = await axios.get(generateUrl('/apps/openregister/api/flow/node-catalog'))\n\t\t\t\tthis.nodeCatalog = response.data?.results || []\n\t\t\t} catch (error) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not load the node catalogue', error)\n\t\t\t\tthis.nodeCatalog = []\n\t\t\t} finally {\n\t\t\t\tthis.catalogLoading = false\n\t\t\t}\n\t\t},\n\n\t\tasync loadEventCatalog() {\n\t\t\ttry {\n\t\t\t\tconst response = await axios.get(generateUrl('/apps/openregister/api/flow/event-catalog'))\n\t\t\t\tthis.eventCatalog = response.data?.results || []\n\t\t\t} catch (error) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not load the event catalogue', error)\n\t\t\t\tthis.eventCatalog = []\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Put the flow named by the route onto the canvas.\n\t\t *\n\t\t * @param {string} id The flow uuid, or 'new'.\n\t\t * @param {string|null} app The owning app for a new flow.\n\t\t * @return {void}\n\t\t */\n\t\topen(id, app = null) {\n\t\t\tthis.selectedNodeId = null\n\t\t\tthis.editingNodeId = null\n\t\t\t// Cleared with the rest of the per-flow state. A refusal left over\n\t\t\t// from the last flow would tell the author their NEW draft is\n\t\t\t// published and offer to draft it again.\n\t\t\tthis.lifecycleRefusal = null\n\t\t\tthis.versions = []\n\t\t\tthis.runs = []\n\t\t\tthis.steps = []\n\t\t\tthis.runObjects = []\n\t\t\tthis.inspectedRunUuid = null\n\t\t\tthis.runDetail = null\n\t\t\tthis.checkResult = null\n\n\t\t\t// A watch is per run and a run is per flow: polling the previous\n\t\t\t// flow's run from the next flow's editor would keep painting a run\n\t\t\t// this canvas cannot show.\n\t\t\tthis.stopWatching()\n\t\t\tthis.watchedRunUuid = null\n\t\t\tthis.watchedRun = null\n\t\t\tthis.watchedSteps = []\n\t\t\tthis.watchedNewFrom = 0\n\t\t\tthis.replayUuid = null\n\n\t\t\t// Cleared on every open, so a not-found id from the previous route\n\t\t\t// cannot keep a resolvable flow behind an error screen.\n\t\t\tthis.notFound = null\n\n\t\t\t// Cleared with the rest of the per-flow state. A snapshot left over\n\t\t\t// from the previous flow's run would keep THIS flow's canvas locked,\n\t\t\t// and `liveGraph` would hold another flow's nodes ready to be\n\t\t\t// restored over it.\n\t\t\tthis.viewingVersion = null\n\t\t\tthis.liveGraph = null\n\t\t\tthis.runGraphNotice = null\n\n\t\t\tif (!id || id === 'new') {\n\t\t\t\t// A new flow is runnable on demand until its author picks a real\n\t\t\t\t// trigger, so the flow-level trigger and the seeded start node\n\t\t\t\t// say the same thing.\n\t\t\t\tthis.flow = { ...emptyFlow(), name: t('nextcloud-vue', 'New flow'), app: app || 'openregister', trigger: 'manual' }\n\t\t\t\tthis.seedStartNode()\n\t\t\t\tthis.dirty = false\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst match = this.flows.find((flow) => String(flow.id) === String(id))\n\t\t\tif (!match) {\n\t\t\t\t// A blank canvas and no explanation is the worst of the three\n\t\t\t\t// possible answers here. `notFound` lets the host say which id it\n\t\t\t\t// could not resolve, so \"this flow was deleted\" and \"this page is\n\t\t\t\t// broken\" stop looking identical.\n\t\t\t\tthis.notFound = String(id)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.flow = {\n\t\t\t\t...emptyFlow(),\n\t\t\t\t...match,\n\t\t\t\t// Deep-copied so an edit on the canvas does not mutate the list\n\t\t\t\t// row behind it — otherwise cancelling an edit leaves the list\n\t\t\t\t// showing changes that were never saved.\n\t\t\t\tnodes: Array.isArray(match.nodes) ? JSON.parse(JSON.stringify(match.nodes)) : [],\n\t\t\t\tedges: Array.isArray(match.edges) ? JSON.parse(JSON.stringify(match.edges)) : [],\n\t\t\t}\n\t\t\tthis.dirty = false\n\n\t\t\t// A flow nobody has ever laid out opens as a PILE, not as a graph.\n\t\t\t//\n\t\t\t// Generated and imported flows carry no coordinates at all — a\n\t\t\t// 76-node flow measured on a live instance had 73 nodes with no\n\t\t\t// position — and every one of those lands on the same point. The\n\t\t\t// result is indistinguishable from an empty canvas: one node's\n\t\t\t// worth of pixels, with the rest underneath it.\n\t\t\t//\n\t\t\t// ⚠️ NOT `autoSort()`. This fallback used to call it, and autoSort\n\t\t\t// gates on `pushUndo()`, which refuses when the graph is locked —\n\t\t\t// and a flow imported from `x-openregister-flows` is PUBLISHED the\n\t\t\t// moment it exists (SchemaFlowImportListener publishes on import).\n\t\t\t// So the exact flows that always need this fallback were the ones\n\t\t\t// it silently skipped: dossiq's 18-node imported flow opened as a\n\t\t\t// pile, with the run replay's badges painting an unreadable point.\n\t\t\t// `applyRenderLayout()` computes coordinates without asking to\n\t\t\t// edit, which a rendering fallback never does.\n\t\t\tthis.applyRenderLayout()\n\n\t\t\tthis.loadRuns(id)\n\t\t},\n\n\t\t/**\n\t\t * Put the one node every flow starts from onto a blank canvas.\n\t\t *\n\t\t * A new flow renders the SAME editor as an existing one, holding only a\n\t\t * starting point — never an empty page that looks like a different\n\t\t * surface. The id is hard-coded rather than read from the catalogue\n\t\t * because the catalogue loads after `open('new')` returns; if an\n\t\t * instance's engine really does not know it, the card wears the\n\t\t * existing \"Unknown step\" warning instead of failing silently.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tseedStartNode() {\n\t\t\tthis.flow.nodes = [{\n\t\t\t\tid: `start-${Date.now().toString(36)}`,\n\t\t\t\ttype: 'openregister.trigger-manual',\n\t\t\t\tx: 80,\n\t\t\t\ty: 60,\n\t\t\t\tconfig: {},\n\t\t\t\tstart: true,\n\t\t\t}]\n\t\t},\n\n\t\t/**\n\t\t * Add a node of `type`, at an explicit canvas point when dropped.\n\t\t *\n\t\t * `type` is the catalogue id verbatim. Default placement stacks a\n\t\t * vertical chain near the left, with a gap about a card high so the\n\t\t * arrowhead and the result badge on the connecting edge both have room.\n\t\t *\n\t\t * @param {string} type The catalogue node id.\n\t\t * @param {number} x Canvas x (optional).\n\t\t * @param {number} y Canvas y (optional).\n\t\t * @return {void}\n\t\t */\n\t\t/**\n\t\t * Remember the current flow so the next edit can be undone.\n\t\t *\n\t\t * Called at the TOP of every mutating action, before the mutation — an\n\t\t * undo stack that records the state AFTER a change can only ever return\n\t\t * you to where you already are.\n\t\t *\n\t\t * Deep-cloned, not referenced. `flow` is mutated in place by several\n\t\t * actions, so a stored reference would be rewritten by the very edit it\n\t\t * exists to reverse and every entry would collapse to \"now\".\n\t\t *\n\t\t * Capped: each entry holds a whole flow document, and a canvas gets a\n\t\t * lot of small edits. 50 is far past what anyone reaches for and still\n\t\t * bounded.\n\t\t *\n\t\t * 🔴 IT ALSO ANSWERS WHETHER THE EDIT MAY HAPPEN AT ALL. Every graph\n\t\t * mutation snapshots here first, which makes this the one place the\n\t\t * published-is-immutable rule can be applied without nine call sites\n\t\t * each remembering to. A locked flow gets `false` and the caller\n\t\t * returns before touching the document — the alternative, letting the\n\t\t * canvas edit freely and discovering the refusal on save, loses the\n\t\t * author's work at the worst possible moment.\n\t\t *\n\t\t * @return {boolean} Whether the caller may proceed with its edit.\n\t\t */\n\t\tpushUndo() {\n\t\t\tif (this.graphLocked) {\n\t\t\t\tthis.lifecycleRefusal = {\n\t\t\t\t\treason: 'version-immutable',\n\t\t\t\t\tlifecycleStatus: this.lifecycleStatus,\n\t\t\t\t}\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\t// The edit is going ahead, so whatever the flow's state last refused\n\t\t\t// is no longer the situation. A refusal that outlives its cause is\n\t\t\t// a message the author learns to ignore, and then ignores the true\n\t\t\t// one too. Cleared HERE for the same reason the lock is checked\n\t\t\t// here: it is the one place every graph mutation passes through.\n\t\t\tthis.lifecycleRefusal = null\n\n\t\t\tthis.snapshot()\n\n\t\t\treturn true\n\t\t},\n\n\t\t/**\n\t\t * Push one undo entry, and keep the stack capped.\n\t\t *\n\t\t * 🔴 THE ONLY PLACE THAT PUSHES. Metadata edits are exempt from the\n\t\t * published-is-immutable lock but still want undo, and the first version\n\t\t * of that exemption pushed to `undoStack` directly — bypassing the trim\n\t\t * and letting the stack grow past its cap (caught at 60/50 by\n\t\t * `useFlowStoreUndo.spec.js`). A cap enforced in two places is a cap\n\t\t * enforced in one of them.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tsnapshot() {\n\t\t\tthis.undoStack.push(JSON.stringify(this.flow))\n\t\t\tif (this.undoStack.length > 50) {\n\t\t\t\tthis.undoStack.shift()\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Step back one edit.\n\t\t *\n\t\t * Entries that match the current state are DISCARDED rather than\n\t\t * applied. Actions snapshot before they know whether they will change\n\t\t * anything — `connect()` refuses a duplicate, `setNodeConfig()` may be\n\t\t * handed the value already stored — so without this a user could press\n\t\t * Ctrl+Z and watch nothing happen, which reads as \"undo is broken\"\n\t\t * rather than \"that edit was a no-op\".\n\t\t *\n\t\t * @return {boolean} Whether anything was undone.\n\t\t */\n\t\tundo() {\n\t\t\tconst current = JSON.stringify(this.flow)\n\n\t\t\twhile (this.undoStack.length > 0) {\n\t\t\t\tconst previous = this.undoStack.pop()\n\t\t\t\tif (previous === current) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tthis.flow = JSON.parse(previous)\n\t\t\t\tthis.dirty = true\n\n\t\t\t\t// The verdict described the graph that was just replaced.\n\t\t\t\tthis.checkResult = null\n\n\t\t\t\t// A node that no longer exists cannot stay selected, and an open\n\t\t\t\t// editor for it would render against nothing.\n\t\t\t\tif (this.nodes.some((node) => node.id === this.selectedNodeId) === false) {\n\t\t\t\t\tthis.selectedNodeId = null\n\t\t\t\t}\n\t\t\t\tif (this.nodes.some((node) => node.id === this.editingNodeId) === false) {\n\t\t\t\t\tthis.editingNodeId = null\n\t\t\t\t}\n\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\treturn false\n\t\t},\n\n\t\taddNode(type, x = null, y = null) {\n\t\t\tif (!this.pushUndo()) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst index = this.nodes.length\n\t\t\tconst node = {\n\t\t\t\tid: `${type}-${Date.now().toString(36)}-${index}`,\n\t\t\t\ttype,\n\t\t\t\tx: x === null ? 80 : x,\n\t\t\t\ty: y === null ? (60 + index * 170) : y,\n\t\t\t\tconfig: {},\n\t\t\t}\n\t\t\tif (index === 0) {\n\t\t\t\tnode.start = true\n\t\t\t}\n\n\t\t\tthis.flow.nodes = [...this.nodes, node]\n\t\t\tthis.selectedNodeId = node.id\n\t\t\tthis.dirty = true\n\t\t\tthis.checkResult = null\n\t\t},\n\n\t\t/**\n\t\t * WRITES BOTH SPELLINGS, FOR THE SAME REASON connect() WRITES `from`/`to`.\n\t\t *\n\t\t * `position: {x, y}` is the shape the SERVER stores — measured on a live\n\t\t * instance, not one of 100 persisted flows carried a flat `x`/`y` node.\n\t\t * Writing only flat coordinates therefore meant a dragged node's new\n\t\t * position never survived the save: it round-tripped back as no position\n\t\t * at all, and the node reloaded at the origin.\n\t\t *\n\t\t * Flat `x`/`y` is kept alongside it because autoSort() and addNode()\n\t\t * speak that spelling in memory, and dropping it here would make a moved\n\t\t * node inconsistent with an unmoved one within the same session.\n\t\t *\n\t\t * @param {object} move The move.\n\t\t * @param {string} move.id The node that moved.\n\t\t * @param {number} move.x Its new x, in canvas units.\n\t\t * @param {number} move.y Its new y.\n\t\t * @return {void}\n\t\t */\n\t\t/**\n\t\t * Duplicate a step, offset so the copy is visibly its own node.\n\t\t *\n\t\t * The config is deep-cloned. A shallow copy would leave both steps\n\t\t * sharing one config object, so editing the duplicate would silently\n\t\t * rewrite the original — the copy would look independent and not be.\n\t\t *\n\t\t * Edges are deliberately NOT copied. A duplicate wired exactly like its\n\t\t * original would fan the flow in two at that point, which is a different\n\t\t * graph from the one the author asked for; they connect the copy where\n\t\t * they want it.\n\t\t *\n\t\t * `start` is not copied either: a flow has one starting point, and a\n\t\t * second node claiming it makes the entry ambiguous.\n\t\t *\n\t\t * @param {string} id The node to copy.\n\t\t * @return {string|null} The new node's id, or null when there was nothing to copy.\n\t\t */\n\t\tcopyNode(id) {\n\t\t\tconst source = this.nodes.find((node) => node.id === id)\n\t\t\tif (source === undefined) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\t// `null`, matching the not-found case above: this method's contract\n\t\t\t// is \"the new node's id, or null when nothing was copied\", and a\n\t\t\t// bare `return` would hand callers `undefined` for one refusal and\n\t\t\t// `null` for the other.\n\t\t\tif (!this.pushUndo()) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\tconst copy = {\n\t\t\t\t...source,\n\t\t\t\tid: `${source.type}-${Date.now().toString(36)}-${this.nodes.length}`,\n\t\t\t\tx: (source.x ?? 0) + 40,\n\t\t\t\ty: (source.y ?? 0) + 40,\n\t\t\t\tconfig: JSON.parse(JSON.stringify(source.config ?? {})),\n\t\t\t}\n\t\t\tcopy.position = { x: copy.x, y: copy.y }\n\t\t\tdelete copy.start\n\t\t\tdelete copy.initial\n\n\t\t\tthis.flow.nodes = [...this.nodes, copy]\n\t\t\tthis.selectedNodeId = copy.id\n\t\t\tthis.dirty = true\n\t\t\tthis.checkResult = null\n\n\t\t\treturn copy.id\n\t\t},\n\n\t\tmoveNode({ id, x, y }) {\n\t\t\tif (!this.pushUndo()) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.flow.nodes = this.nodes.map((node) => (node.id === id ? { ...node, x, y, position: { x, y } } : node))\n\t\t\tthis.dirty = true\n\t\t},\n\n\t\t/**\n\t\t * Connect two nodes (no duplicates, no self-edges).\n\t\t *\n\t\t * WRITES `from`/`to`, WHICH IS THE DIALECT THE ENGINE READS.\n\t\t *\n\t\t * This used to store `{source, target}`. The canvas rendered it — the\n\t\t * `canvasEdges` getter accepts either spelling — so the author saw the\n\t\t * connection, and the save succeeded. But OpenRegister's flow engine\n\t\t * only understands `from`/`to`, so every edge drawn in the editor was\n\t\t * INVISIBLE to it: the saved flow validated with a `node-dead-end`\n\t\t * warning and a run was refused outright with \"node … has no outgoing\n\t\t * edge and does not end the flow\".\n\t\t *\n\t\t * The editor could therefore not produce a runnable multi-node flow at\n\t\t * all, while looking like it had. Measured against a live instance:\n\t\t * `edges: [{source, target}]` returns that warning, `[{from, to}]`\n\t\t * returns clean.\n\t\t *\n\t\t * The duplicate check reads BOTH spellings, so a flow loaded from the\n\t\t * server (which is `from`/`to`) is not re-connected into a duplicate.\n\t\t *\n\t\t * @param {object} payload The connection.\n\t\t * @param {string} payload.source Source node id.\n\t\t * @param {string} payload.target Target node id.\n\t\t * @return {void}\n\t\t */\n\t\tconnect({ source, target }) {\n\t\t\tif (!this.pushUndo()) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (!source || !target || source === target) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst exists = this.edges.some((edge) => (edge.source ?? edge.from) === source && (edge.target ?? edge.to) === target)\n\t\t\tif (exists) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.flow.edges = [...this.edges, { from: source, to: target }]\n\t\t\tthis.dirty = true\n\t\t\tthis.checkResult = null\n\t\t},\n\n\t\t/**\n\t\t * The stored edge a drawn line came from, and how it is stored.\n\t\t *\n\t\t * Both dialects and both cardinalities: an edge may speak\n\t\t * `{source, target}` or `{from, to}`, and either endpoint may be a LIST\n\t\t * (several `from` is a join, several `to` is a split). So \"the edge for\n\t\t * line a→c\" is not simply `edges.find(...)` — it may be one entry among\n\t\t * three that the same record draws.\n\t\t *\n\t\t * @param {object} line The line.\n\t\t * @param {string} line.source Its source node id.\n\t\t * @param {string} line.target Its target node id.\n\t\t * @return {{index: number, edge: object, sourceKey: string, targetKey: string, sources: Array<string>, targets: Array<string>}|null}\n\t\t * Where it lives, or null when no stored edge draws it.\n\t\t */\n\t\tlocateEdge({ source, target }) {\n\t\t\tconst toList = (value) => {\n\t\t\t\tif (Array.isArray(value)) {\n\t\t\t\t\treturn value.filter((v) => v !== null && v !== undefined && v !== '')\n\t\t\t\t}\n\n\t\t\t\treturn (value === null || value === undefined || value === '') ? [] : [value]\n\t\t\t}\n\n\t\t\tconst edges = this.edges\n\t\t\tfor (let index = 0; index < edges.length; index++) {\n\t\t\t\tconst edge = edges[index]\n\t\t\t\tconst sourceKey = edge.source !== undefined ? 'source' : 'from'\n\t\t\t\tconst targetKey = edge.target !== undefined ? 'target' : 'to'\n\t\t\t\tconst sources = toList(edge[sourceKey])\n\t\t\t\tconst targets = toList(edge[targetKey])\n\n\t\t\t\tif (sources.includes(source) && targets.includes(target)) {\n\t\t\t\t\treturn { index, edge, sourceKey, targetKey, sources, targets }\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn null\n\t\t},\n\n\t\t/**\n\t\t * Remove ONE drawn connection.\n\t\t *\n\t\t * ⚠️ ONE LINE, NOT ONE RECORD. Deleting a→c out of `{from: 'a', to:\n\t\t * ['b','c']}` must leave a→b standing: dropping the whole record because\n\t\t * it happens to be where a→c is stored would silently delete a second\n\t\t * connection the author never selected. So a multi-line record is\n\t\t * narrowed rather than removed, and only a record left with nothing on\n\t\t * one end goes.\n\t\t *\n\t\t * @param {object} line The line to remove.\n\t\t * @param {string} line.source Its source node id.\n\t\t * @param {string} line.target Its target node id.\n\t\t * @return {void}\n\t\t */\n\t\tremoveEdge({ source, target }) {\n\t\t\tconst found = this.locateEdge({ source, target })\n\t\t\tif (found === null) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (!this.pushUndo()) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst targets = found.targets.filter((id) => id !== target)\n\t\t\tconst sources = found.sources.length > 1 ? found.sources.filter((id) => id !== source) : found.sources\n\n\t\t\tconst edges = [...this.edges]\n\t\t\tif (targets.length === 0 || sources.length === 0) {\n\t\t\t\tedges.splice(found.index, 1)\n\t\t\t} else {\n\t\t\t\tedges[found.index] = {\n\t\t\t\t\t...found.edge,\n\t\t\t\t\t[found.sourceKey]: sources.length === 1 ? sources[0] : sources,\n\t\t\t\t\t[found.targetKey]: targets.length === 1 ? targets[0] : targets,\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.flow.edges = edges\n\t\t\tthis.dirty = true\n\t\t\tthis.checkResult = null\n\t\t},\n\n\t\t/**\n\t\t * Set a field — `title`, `lineType` — on ONE drawn connection.\n\t\t *\n\t\t * ⚠️ SPLITS A MULTI-LINE RECORD FIRST. Writing `lineType` straight onto\n\t\t * `{from: 'a', to: ['b','c']}` would restyle both lines from a control\n\t\t * the author opened on one of them. A per-line control whose blast\n\t\t * radius is three lines is not a per-line control, so the line being\n\t\t * edited is lifted into a record of its own and the field is set there.\n\t\t *\n\t\t * Takes a whole set of fields rather than one, so pasting a copied\n\t\t * presentation is a SINGLE undo step. Two `key`/`value` calls in a row\n\t\t * would leave a user pressing Ctrl+Z twice to reverse one paste, and the\n\t\t * first press would land on a half-pasted line.\n\t\t *\n\t\t * @param {object} change The change.\n\t\t * @param {string} change.source The line's source node id.\n\t\t * @param {string} change.target The line's target node id.\n\t\t * @param {object} change.fields The fields to set, as a plain object.\n\t\t * @return {void}\n\t\t */\n\t\tsetEdgeFields({ source, target, fields }) {\n\t\t\tconst found = this.locateEdge({ source, target })\n\t\t\tif (found === null) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (!this.pushUndo()) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst edges = [...this.edges]\n\t\t\tconst drawsOneLine = found.sources.length === 1 && found.targets.length === 1\n\n\t\t\tif (drawsOneLine) {\n\t\t\t\tedges[found.index] = { ...found.edge, ...fields }\n\t\t\t} else {\n\t\t\t\t// Narrow the record to the lines this one is NOT, then append the\n\t\t\t\t// edited line as its own record.\n\t\t\t\tconst remainingTargets = found.targets.filter((id) => id !== target)\n\t\t\t\tedges[found.index] = {\n\t\t\t\t\t...found.edge,\n\t\t\t\t\t[found.targetKey]: remainingTargets.length === 1 ? remainingTargets[0] : remainingTargets,\n\t\t\t\t}\n\t\t\t\tedges.push({\n\t\t\t\t\t...found.edge,\n\t\t\t\t\tid: undefined,\n\t\t\t\t\t[found.sourceKey]: source,\n\t\t\t\t\t[found.targetKey]: target,\n\t\t\t\t\t...fields,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tthis.flow.edges = edges\n\t\t\tthis.dirty = true\n\t\t\tthis.checkResult = null\n\t\t},\n\n\t\t/**\n\t\t * Copy a connection's presentation, for pasting onto another.\n\t\t *\n\t\t * @param {object} line The line to copy from.\n\t\t * @param {string} line.source Its source node id.\n\t\t * @param {string} line.target Its target node id.\n\t\t * @return {void}\n\t\t */\n\t\tcopyEdgeStyle({ source, target }) {\n\t\t\tconst found = this.locateEdge({ source, target })\n\t\t\tif (found === null) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.edgeStyleClipboard = {\n\t\t\t\ttitle: found.edge.title ?? found.edge.label ?? '',\n\t\t\t\tlineType: found.edge.lineType || DEFAULT_EDGE_LINE_TYPE,\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Apply the copied presentation to another connection.\n\t\t *\n\t\t * @param {object} line The line to paste onto.\n\t\t * @param {string} line.source Its source node id.\n\t\t * @param {string} line.target Its target node id.\n\t\t * @return {void}\n\t\t */\n\t\tpasteEdgeStyle({ source, target }) {\n\t\t\tconst copied = this.edgeStyleClipboard\n\t\t\tif (copied === null) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.setEdgeFields({ source, target, fields: { lineType: copied.lineType, title: copied.title } })\n\t\t},\n\n\t\tremoveNode(id) {\n\t\t\tif (!this.pushUndo()) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.flow.nodes = this.nodes.filter((node) => node.id !== id)\n\t\t\t// BOTH spellings, or removing a node leaves its `from`/`to` edges\n\t\t\t// behind pointing at a node that no longer exists — and `from`/`to`\n\t\t\t// is exactly what the server stores, so every edge on a loaded flow\n\t\t\t// survived the deletion of the node it referenced.\n\t\t\tthis.flow.edges = this.edges.filter((edge) => (edge.source ?? edge.from) !== id && (edge.target ?? edge.to) !== id)\n\t\t\tthis.selectedNodeId = null\n\t\t\t// A dialog open on a line that ran through this node now describes\n\t\t\t// a connection the document no longer holds; every edge action would\n\t\t\t// find nothing and quietly do nothing.\n\t\t\tif (this.editingEdge?.source === id || this.editingEdge?.target === id) {\n\t\t\t\tthis.editingEdge = null\n\t\t\t}\n\t\t\tthis.dirty = true\n\t\t\tthis.checkResult = null\n\t\t},\n\n\t\t/**\n\t\t * Replace the selected node's whole config.\n\t\t *\n\t\t * The raw-config editor needs this: it edits the object as a document, so\n\t\t * a per-key setter could never REMOVE a key, and a node type whose keys\n\t\t * the builder does not know would accumulate stale ones.\n\t\t *\n\t\t * @param {object} config The new config object.\n\t\t * @return {void}\n\t\t */\n\t\tsetNodeConfigAll(config) {\n\t\t\tif (!this.pushUndo()) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (this.selectedNodeId === null) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.flow.nodes = this.nodes.map((node) => (\n\t\t\t\tnode.id === this.selectedNodeId ? { ...node, config: { ...config } } : node\n\t\t\t))\n\t\t\tthis.dirty = true\n\t\t\tthis.checkResult = null\n\t\t},\n\n\t\tsetNodeConfig(key, value) {\n\t\t\tif (!this.pushUndo()) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (this.selectedNodeId === null) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.flow.nodes = this.nodes.map((node) => (\n\t\t\t\tnode.id === this.selectedNodeId\n\t\t\t\t\t? { ...node, config: { ...(node.config || {}), [key]: value } }\n\t\t\t\t\t: node\n\t\t\t))\n\t\t\tthis.dirty = true\n\t\t\tthis.checkResult = null\n\t\t},\n\n\t\tsetFlowField(key, value) {\n\t\t\t// 🔴 THE LOCK APPLIES TO THE FOUR GRAPH KEYS AND NO OTHERS, exactly\n\t\t\t// where the server draws the line. `executionMode` and `limits` are\n\t\t\t// part of the pinned definition; `name`, `description` and `enabled`\n\t\t\t// are not — renaming a live process or switching it off are not\n\t\t\t// changes to the process. Locking those too would refuse edits the\n\t\t\t// API accepts and leave a published flow unmanageable.\n\t\t\tif (GRAPH_FIELDS.includes(key)) {\n\t\t\t\tif (!this.pushUndo()) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.snapshot()\n\t\t\t}\n\n\t\t\tthis.flow = { ...this.flow, [key]: value }\n\t\t\tthis.dirty = true\n\t\t},\n\n\t\t/**\n\t\t * Rename one node. The name is display only — the card's headline —\n\t\t * so it does not invalidate a check verdict.\n\t\t *\n\t\t * @param {string} id The node id.\n\t\t * @param {string} name The new name; empty falls back to the type label.\n\t\t * @return {void}\n\t\t */\n\t\tsetNodeName(id, name) {\n\t\t\tif (!this.pushUndo()) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.flow.nodes = this.nodes.map((node) => (\n\t\t\t\tnode.id === id ? { ...node, name } : node\n\t\t\t))\n\t\t\tthis.dirty = true\n\t\t},\n\n\t\t/**\n\t\t * Replace one node's whole config, by id.\n\t\t *\n\t\t * The edit dialog needs this: it commits a DRAFT on Done, for whichever\n\t\t * node it was opened on — which is not necessarily the selected one.\n\t\t *\n\t\t * @param {string} id The node id.\n\t\t * @param {object} config The new config object.\n\t\t * @return {void}\n\t\t */\n\t\tsetNodeConfigById(id, config) {\n\t\t\tif (!this.pushUndo()) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.flow.nodes = this.nodes.map((node) => (\n\t\t\t\tnode.id === id ? { ...node, config: { ...config } } : node\n\t\t\t))\n\t\t\tthis.dirty = true\n\t\t\tthis.checkResult = null\n\t\t},\n\n\t\t/**\n\t\t * Whether a node carries a position of its own.\n\t\t *\n\t\t * BOTH SPELLINGS, because both are in circulation: the server stores\n\t\t * `position: {x, y}` and the editor writes flat `x`/`y` in memory.\n\t\t * Checking only one would read a positioned flow as unpositioned and\n\t\t * rearrange it — the opposite of what load() wants.\n\t\t *\n\t\t * A node AT the origin counts as positioned. (0, 0) is a legitimate\n\t\t * place to put something, and treating it as \"no position\" would keep\n\t\t * relaying out a flow whose author had parked a node there.\n\t\t *\n\t\t * @param {object} node The node.\n\t\t * @return {boolean} True when the node says where it goes.\n\t\t */\n\t\thasPosition(node) {\n\t\t\treturn Number.isFinite(Number(node?.x))\n\t\t\t\t|| Number.isFinite(Number(node?.position?.x))\n\t\t},\n\n\t\t/**\n\t\t * Lay the nodes out left-to-right by how the flow actually runs.\n\t\t *\n\t\t * The pass lives in `flowGraphLayout.js`: longest-path layering seeded\n\t\t * from the start nodes with back edges dropped (a loop terminates the\n\t\t * layering instead of stretching it), one barycenter ordering pass per\n\t\t * column so parallel branches stay apart, fixed grid spacing.\n\t\t * Unreachable nodes go one column past everything — never at the\n\t\t * origin, where they would hide under the entry points. Coordinates\n\t\t * and NOTHING else change, which is what makes this safe to press on\n\t\t * a working flow.\n\t\t *\n\t\t * This is the EDIT — the toolbar button. It asks `pushUndo()` first,\n\t\t * so a locked graph refuses it, and it marks the document dirty so the\n\t\t * new layout is offered for saving. The rendering fallback that may\n\t\t * not do either of those things is `applyRenderLayout()`.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tautoSort() {\n\t\t\tif (!this.pushUndo()) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (!this.nodes.length) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.flow.nodes = layoutFlowNodes(this.nodes, this.canvasEdges, this.startNodeIds)\n\t\t\tthis.dirty = true\n\t\t},\n\n\t\t/**\n\t\t * Give every node a usable position, without editing anything.\n\t\t *\n\t\t * A rendering fallback, not an edit: no undo entry, no dirty flag, no\n\t\t * lifecycle refusal — which is what lets it run on a PUBLISHED flow,\n\t\t * where `autoSort()` correctly refuses. The definition is untouched as\n\t\t * far as anyone else can tell: the coordinates live on the in-memory\n\t\t * copy `open()` already deep-cloned, nothing here persists them, and a\n\t\t * viewer who only looks never writes them anywhere. On a DRAFT the\n\t\t * author goes on to edit, the next save carries them along the\n\t\t * existing save path — which is the point: a once-opened flow becomes\n\t\t * stable instead of being relaid on every visit.\n\t\t *\n\t\t * Two cases, decided by the positions actually present:\n\t\t *\n\t\t * - No usable positions at all — none, or every positioned node piled\n\t\t * on one identical point — lays the WHOLE graph out fresh.\n\t\t * - An arranged graph with some position-less nodes keeps every placed\n\t\t * node exactly where its author put it and slots only the loose ones\n\t\t * beneath, in run order.\n\t\t *\n\t\t * @return {boolean} Whether any node was given a position.\n\t\t */\n\t\tapplyRenderLayout() {\n\t\t\tconst nodes = this.flow.nodes || []\n\t\t\tif (!nodes.length) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\tif (needsFullLayout(nodes)) {\n\t\t\t\tthis.flow.nodes = layoutFlowNodes(nodes, this.canvasEdges, this.startNodeIds)\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\tif (nodes.some((node) => !this.hasPosition(node))) {\n\t\t\t\tthis.flow.nodes = placeLooseNodes(nodes, this.canvasEdges, this.startNodeIds)\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\treturn false\n\t\t},\n\n\t\t/**\n\t\t * Ask the engine whether the CANVAS is runnable, without saving it.\n\t\t *\n\t\t * `POST /api/flow/validate` preflights the document against the live\n\t\t * node registry — the same check a save performs, minus the write. A\n\t\t * refusal (400) still carries the preflight's own report, so it is kept\n\t\t * as the result rather than treated as a transport failure: \"this flow\n\t\t * is not runnable, and here is why\" is the answer the button asked for.\n\t\t *\n\t\t * @return {Promise<object|null>} `{valid, blocking, warnings, message?}`, or null.\n\t\t */\n\t\tasync check() {\n\t\t\tthis.checking = true\n\t\t\tthis.error = null\n\t\t\ttry {\n\t\t\t\tconst response = await axios.post(\n\t\t\t\t\tgenerateUrl('/apps/openregister/api/flow/validate'),\n\t\t\t\t\t{ flow: this.flowForRun },\n\t\t\t\t)\n\t\t\t\tthis.checkResult = response.data || null\n\t\t\t\treturn this.checkResult\n\t\t\t} catch (error) {\n\t\t\t\tconst report = error?.response?.data\n\t\t\t\tif (report && typeof report === 'object' && 'valid' in report) {\n\t\t\t\t\tthis.checkResult = report\n\t\t\t\t\treturn this.checkResult\n\t\t\t\t}\n\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not check the flow', error)\n\t\t\t\tthis.error = error\n\t\t\t\treturn null\n\t\t\t} finally {\n\t\t\t\tthis.checking = false\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Create or update the flow.\n\t\t *\n\t\t * `owner` and `organisation` are never sent: the server stamps them, and\n\t\t * a client-supplied owner would let an author mint a flow that RUNS as\n\t\t * somebody else.\n\t\t *\n\t\t * 🔴 A VERSION SNAPSHOT IS NEVER SAVED, AND THE UI IS NOT THE GUARD.\n\t\t *\n\t\t * While `viewingVersion` is set the canvas holds a HISTORIC graph and\n\t\t * `flow.id` still names the live flow, so the PUT below would overwrite\n\t\t * the current flow with an old graph. The disabled Save button is not\n\t\t * protection: this method is also reached by the keyboard shortcut, and\n\t\t * the server only refuses a PUBLISHED flow — a flow that was published,\n\t\t * run, and then drafted again has version rows to inspect AND accepts\n\t\t * writes, which is exactly the combination that loses the graph.\n\t\t *\n\t\t * Returning null rather than throwing: nothing has gone wrong, the save\n\t\t * simply does not apply to what is on screen.\n\t\t *\n\t\t * @return {Promise<object|null>} The stored flow, or null on failure.\n\t\t */\n\t\tasync save() {\n\t\t\tif (this.viewingVersion !== null) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\tthis.saving = true\n\t\t\tthis.error = null\n\t\t\ttry {\n\t\t\t\tconst payload = { ...this.flow }\n\t\t\t\tdelete payload.owner\n\t\t\t\tdelete payload.organisation\n\n\t\t\t\tconst isNew = !payload.id\n\t\t\t\tconst response = isNew\n\t\t\t\t\t? await axios.post(generateUrl('/apps/openregister/api/flows'), payload)\n\t\t\t\t\t: await axios.put(generateUrl(`/apps/openregister/api/flows/${payload.id}`), payload)\n\n\t\t\t\tconst saved = response.data || null\n\t\t\t\tif (saved?.id) {\n\t\t\t\t\tthis.flow = { ...this.flow, id: saved.id }\n\t\t\t\t}\n\n\t\t\t\tawait this.load({ app: this.flow.app })\n\t\t\t\tthis.dirty = false\n\t\t\t\treturn saved\n\t\t\t} catch (error) {\n\t\t\t\t// A 409 is not a failure to save; it is the flow's STATE saying\n\t\t\t\t// this edit needs a draft first. Kept as the server's fields so\n\t\t\t\t// the sidebar can offer \"create a draft version\" rather than a\n\t\t\t\t// generic error nobody can act on.\n\t\t\t\tif (error?.response?.status === 409) {\n\t\t\t\t\tthis.lifecycleRefusal = {\n\t\t\t\t\t\treason: error.response.data?.reason || 'version-immutable',\n\t\t\t\t\t\tlifecycleStatus: error.response.data?.lifecycleStatus || null,\n\t\t\t\t\t}\n\t\t\t\t\treturn null\n\t\t\t\t}\n\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not save the flow', error)\n\t\t\t\tthis.error = error\n\t\t\t\treturn null\n\t\t\t} finally {\n\t\t\t\tthis.saving = false\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Publish the open flow's draft, so it backs new runs.\n\t\t *\n\t\t * Runs already in flight are untouched: they are pinned to the version\n\t\t * they started on, which is the whole point of publishing being an\n\t\t * event rather than a save.\n\t\t *\n\t\t * @param {string|null} bump The semver component to advance ('major' |\n\t\t * 'minor' | 'patch'), or null to let the server\n\t\t * decide from what actually changed.\n\t\t * @return {Promise<object|null>} The published version, or null.\n\t\t */\n\t\tasync publish(bump = null) {\n\t\t\treturn await this.transition('publish', (bump ? { bump } : null))\n\t\t},\n\n\t\t/**\n\t\t * Ask what publishing would be called, without publishing.\n\t\t *\n\t\t * A GET that changes nothing. The author is asking before they commit\n\t\t * to an answer, so a refusal here would make it impossible to find out\n\t\t * that a change is breaking without first asserting that it is not.\n\t\t *\n\t\t * @return {Promise<object|null>} The preview, or null when it could not\n\t\t * be fetched.\n\t\t */\n\t\tasync previewPublish() {\n\t\t\tif (!this.flow.id) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\tthis.previewingPublish = true\n\t\t\tthis.versionBumpRefusal = null\n\n\t\t\ttry {\n\t\t\t\tconst response = await axios.get(generateUrl(`/apps/openregister/api/flows/${this.flow.id}/version-preview`))\n\t\t\t\tthis.publishPreview = response.data || null\n\t\t\t\treturn this.publishPreview\n\t\t\t} catch (error) {\n\t\t\t\t// 🔑 A PREVIEW THAT FAILS MUST NOT BLOCK THE PUBLISH. It is a\n\t\t\t\t// courtesy, and an instance whose route is older than this\n\t\t\t\t// build would otherwise lose the ability to publish at all.\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not preview the next version', error)\n\t\t\t\tthis.publishPreview = null\n\t\t\t\treturn null\n\t\t\t} finally {\n\t\t\t\tthis.previewingPublish = false\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Create a draft version from the published one.\n\t\t *\n\t\t * The published version keeps serving until the draft is published, so\n\t\t * editing a live process never takes it offline.\n\t\t *\n\t\t * @return {Promise<object|null>} The new draft version, or null.\n\t\t */\n\t\tasync createDraft() {\n\t\t\treturn await this.transition('draft')\n\t\t},\n\n\t\t/**\n\t\t * Retire the published version, so the flow backs no new runs.\n\t\t *\n\t\t * @return {Promise<object|null>} The deprecated version, or null.\n\t\t */\n\t\tasync deprecate() {\n\t\t\treturn await this.transition('deprecate')\n\t\t},\n\n\t\t/**\n\t\t * POST one lifecycle transition and reload the flow it changed.\n\t\t *\n\t\t * 🔑 THE RELOAD IS NOT OPTIONAL. A transition changes `version` and\n\t\t * `lifecycleStatus`, and those decide whether the canvas is editable.\n\t\t * Leaving the client's copy stale would show an author an editable\n\t\t * canvas over a version the server will refuse to write.\n\t\t *\n\t\t * @param {string} action `publish`, `draft` or `deprecate`.\n\t\t * @param {object|null} body What to send with it, such as `{bump}`.\n\t\t * @return {Promise<object|null>} The resulting version, or null.\n\t\t */\n\t\tasync transition(action, body = null) {\n\t\t\tif (!this.flow.id) {\n\t\t\t\tthis.error = new Error('Save the flow before changing its lifecycle.')\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\tthis.transitioning = true\n\t\t\tthis.lifecycleRefusal = null\n\t\t\tthis.versionBumpRefusal = null\n\n\t\t\ttry {\n\t\t\t\t// 🔑 NO BODY MEANS NO SECOND ARGUMENT. `draft` and `deprecate`\n\t\t\t\t// take nothing, and sending them an empty object changes the\n\t\t\t\t// call every caller and test has ever seen for the sake of a\n\t\t\t\t// parameter only `publish` uses.\n\t\t\t\tconst url = generateUrl(`/apps/openregister/api/flows/${this.flow.id}/${action}`)\n\t\t\t\tconst response = body\n\t\t\t\t\t? await axios.post(url, body)\n\t\t\t\t\t: await axios.post(url)\n\n\t\t\t\t// RELOAD THE LIST FIRST. `open()` reads from `this.flows`, not\n\t\t\t\t// from the server, so opening without reloading would restore\n\t\t\t\t// the pre-transition copy and show a published flow as still a\n\t\t\t\t// draft — with an editable canvas over it.\n\t\t\t\tconst id = this.flow.id\n\t\t\t\tconst app = this.flow.app\n\t\t\t\tawait this.load({ app })\n\t\t\t\tthis.open(id, app)\n\t\t\t\tawait this.loadVersions()\n\n\t\t\t\treturn response.data || null\n\t\t\t} catch (error) {\n\t\t\t\tif (error?.response?.status === 409) {\n\t\t\t\t\t// 🔑 TWO DIFFERENT 409s. `version-bump-refused` means the\n\t\t\t\t\t// flow is fine and the REQUEST was wrong — the author asked\n\t\t\t\t\t// to call a removal minor — and its remedy is to publish it\n\t\t\t\t\t// as major, not to create a draft. Reading both as a\n\t\t\t\t\t// lifecycle refusal offers the wrong button.\n\t\t\t\t\tif (error.response.data?.kind === 'version-bump-refused') {\n\t\t\t\t\t\tthis.versionBumpRefusal = error.response.data?.error || null\n\t\t\t\t\t\treturn null\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.lifecycleRefusal = {\n\t\t\t\t\t\treason: error.response.data?.reason || null,\n\t\t\t\t\t\tlifecycleStatus: error.response.data?.lifecycleStatus || null,\n\t\t\t\t\t}\n\t\t\t\t\treturn null\n\t\t\t\t}\n\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error(`cn-flow: could not ${action} the flow`, error)\n\t\t\t\tthis.error = error\n\t\t\t\treturn null\n\t\t\t} finally {\n\t\t\t\tthis.transitioning = false\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Load every version of the open flow, newest first.\n\t\t *\n\t\t * @return {Promise<Array>} The versions.\n\t\t */\n\t\tasync loadVersions() {\n\t\t\tif (!this.flow.id) {\n\t\t\t\tthis.versions = []\n\t\t\t\treturn this.versions\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst response = await axios.get(generateUrl(`/apps/openregister/api/flows/${this.flow.id}/versions`))\n\t\t\t\tthis.versions = response.data?.results || []\n\t\t\t} catch (error) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not read the flow versions', error)\n\t\t\t\tthis.versions = []\n\t\t\t}\n\n\t\t\treturn this.versions\n\t\t},\n\n\t\t/**\n\t\t * Delete a flow, then reload the list.\n\t\t *\n\t\t * The reload scope matters: the editor deletes the OPEN flow, so\n\t\t * `this.flow.app` is the right scope there — but an index page deletes\n\t\t * a ROW while no flow is open, and `this.flow.app` is then blank,\n\t\t * which reloads EVERY app's flows into a list that was scoped to one.\n\t\t * Callers that know their scope pass it; the default keeps the\n\t\t * editor's behaviour.\n\t\t *\n\t\t * @param {string} id The flow id or uuid.\n\t\t * @param {object} [options] Reload options.\n\t\t * @param {string|null} [options.app] The app scope to reload with;\n\t\t * when omitted, the open flow's app is used.\n\t\t * @return {Promise<void>} Resolves when deleted and reloaded.\n\t\t */\n\t\tasync remove(id, options = {}) {\n\t\t\tawait axios.delete(generateUrl(`/apps/openregister/api/flows/${id}`))\n\t\t\tconst app = ('app' in options) ? options.app : this.flow.app\n\t\t\tawait this.load({ app })\n\t\t},\n\n\t\t/**\n\t\t * Copy a stored flow under a new name, then reload the list.\n\t\t *\n\t\t * Reads the STORED flow (`GET /api/flows/{id}`) rather than trusting a\n\t\t * list row, and re-posts its editable fields. Identity and lifecycle\n\t\t * are deliberately not copied: `FlowController::create()`'s allowlist\n\t\t * would refuse them anyway (owner is stamped from the session,\n\t\t * lifecycle starts fresh), but stripping them here documents that a\n\t\t * copy is a NEW flow — same graph, nobody's history.\n\t\t *\n\t\t * @param {string} id The flow to copy.\n\t\t * @param {string} name The copy's name.\n\t\t * @param {object} [options] Reload options.\n\t\t * @param {string|null} [options.app] The app scope to reload with.\n\t\t * @return {Promise<object>} The created flow.\n\t\t */\n\t\tasync duplicate(id, name, options = {}) {\n\t\t\tconst response = await axios.get(generateUrl(`/apps/openregister/api/flows/${id}`))\n\t\t\tconst {\n\t\t\t\tid: _id,\n\t\t\t\tuuid: _uuid,\n\t\t\t\towner: _owner,\n\t\t\t\torganisation: _organisation,\n\t\t\t\tcreated: _created,\n\t\t\t\tupdated: _updated,\n\t\t\t\tlifecycleStatus: _lifecycleStatus,\n\t\t\t\tversion: _version,\n\t\t\t\t...editable\n\t\t\t} = response.data || {}\n\t\t\tconst createResponse = await axios.post(\n\t\t\t\tgenerateUrl('/apps/openregister/api/flows'),\n\t\t\t\t{ ...editable, name },\n\t\t\t)\n\t\t\tconst app = ('app' in options) ? options.app : this.flow.app\n\t\t\tawait this.load({ app })\n\t\t\treturn createResponse.data\n\t\t},\n\n\t\t/**\n\t\t * Run the stored flow, immediately or queued, as the flow itself says.\n\t\t *\n\t\t * A flow must be SAVED before it runs. The engine walks the stored\n\t\t * document, so running unsaved canvas state would report on a graph that\n\t\t * is not the one on screen.\n\t\t *\n\t\t * 🔴 `executionMode` DECIDES, AND IT WAS NEVER SENT. This POST carried\n\t\t * only the subject, so the endpoint fell back to its async default and\n\t\t * every press of Run produced a row reading `queued` — including for a\n\t\t * flow the author had explicitly set to run synchronously. The endpoint\n\t\t * has accepted `sync` all along; nothing was asking for it.\n\t\t *\n\t\t * A sync run answers with the FINISHED run rather than a queued one,\n\t\t * which is what a person standing in front of the button expects. An\n\t\t * async flow still queues, because that is what async means.\n\t\t *\n\t\t * @param {object} subject `{uuid, register, schema}` of the subject.\n\t\t * @return {Promise<object|null>} The run, finished or queued.\n\t\t */\n\t\tasync run(subject = {}) {\n\t\t\tif (!this.flow.id) {\n\t\t\t\tthis.error = new Error('Save the flow before running it.')\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\tthis.running = true\n\t\t\ttry {\n\t\t\t\tconst response = await axios.post(\n\t\t\t\t\tgenerateUrl(`/apps/openregister/api/flows/${this.flow.id}/run`),\n\t\t\t\t\t{ subject, sync: this.runsSynchronously },\n\t\t\t\t)\n\t\t\t\tawait this.loadRuns(this.flow.id)\n\n\t\t\t\t// The POST answers with the created run, uuid included. That\n\t\t\t\t// uuid used to be discarded, which is why pressing Run left a\n\t\t\t\t// perfectly still canvas: nothing ever looked at the run again\n\t\t\t\t// until the user opened the Runs tab. Watching it is what puts\n\t\t\t\t// the run ON the canvas.\n\t\t\t\tconst run = response.data || null\n\t\t\t\tif (run?.uuid) {\n\t\t\t\t\tthis.watchRun(run.uuid)\n\t\t\t\t}\n\n\t\t\t\treturn run\n\t\t\t} catch (error) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not run the flow', error)\n\t\t\t\tthis.error = error\n\t\t\t\treturn null\n\t\t\t} finally {\n\t\t\t\tthis.running = false\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Watch one run: poll it while its status is non-terminal.\n\t\t *\n\t\t * Polls `GET /apps/openregister/api/flow-runs/{uuid}` on an interval\n\t\t * (default 3s, floored at 2s), stops by itself on a terminal status,\n\t\t * on a re-watch, and on teardown. Pauses while the document is hidden\n\t\t * and resumes with one immediate fetch when it becomes visible — the\n\t\t * behaviour CnFlowRunsWidget already ships.\n\t\t *\n\t\t * Polling, not push, because that is what exists: the flow-run API is\n\t\t * REST only, and the engine persists the log once per worker pass\n\t\t * anyway, so a push channel would today deliver the same bursts.\n\t\t *\n\t\t * @param {string} uuid The run to watch.\n\t\t * @param {object} options Watch options.\n\t\t * @param {number} options.intervalMs Poll interval in ms; floored at 2000.\n\t\t * @return {void}\n\t\t */\n\t\twatchRun(uuid, { intervalMs = WATCH_INTERVAL_DEFAULT_MS } = {}) {\n\t\t\tthis.stopWatching()\n\n\t\t\tif (!uuid) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.watchedRunUuid = uuid\n\t\t\tthis.watchedRun = null\n\t\t\tthis.watchedSteps = []\n\t\t\tthis.watchedNewFrom = 0\n\t\t\tthis.watching = true\n\n\t\t\tconst requested = Number(intervalMs)\n\t\t\tthis._watchIntervalMs = Math.max(\n\t\t\t\tWATCH_INTERVAL_FLOOR_MS,\n\t\t\t\tNumber.isFinite(requested) ? requested : WATCH_INTERVAL_DEFAULT_MS,\n\t\t\t)\n\n\t\t\t// Bound so removeEventListener gets the SAME function back — an\n\t\t\t// inline arrow here could be added but never removed.\n\t\t\tthis._watchOnVisibility = () => this.onWatchVisibilityChange()\n\t\t\tdocument.addEventListener('visibilitychange', this._watchOnVisibility)\n\n\t\t\tthis.fetchWatchedRun()\n\t\t\tthis.startWatchTimer()\n\t\t},\n\n\t\t/**\n\t\t * Start (or restart) the poll interval — unless the watch is over or\n\t\t * the tab is hidden, in which case the visibility handler restarts it.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tstartWatchTimer() {\n\t\t\tthis.clearWatchTimer()\n\n\t\t\tif (this.watching !== true || document.hidden === true) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis._watchTimer = setInterval(() => {\n\t\t\t\tthis.fetchWatchedRun()\n\t\t\t}, this._watchIntervalMs)\n\t\t},\n\n\t\t/**\n\t\t * Clear the poll interval. The watch itself stays what it was.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tclearWatchTimer() {\n\t\t\tif (this._watchTimer !== undefined && this._watchTimer !== null) {\n\t\t\t\tclearInterval(this._watchTimer)\n\t\t\t\tthis._watchTimer = null\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * One poll of the watched run.\n\t\t *\n\t\t * Appends the log entries beyond what `watchedSteps` already holds —\n\t\t * the log only grows within a run, so the index diff is exact and an\n\t\t * already-exposed step is never replayed. Stops the watch when the\n\t\t * status turns terminal, keeping the final run and steps for the\n\t\t * canvas's last paint.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync fetchWatchedRun() {\n\t\t\tconst uuid = this.watchedRunUuid\n\t\t\tif (!uuid) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst response = await axios.get(generateUrl(`/apps/openregister/api/flow-runs/${uuid}`))\n\n\t\t\t\t// A re-watch can land while this request is in the air; its\n\t\t\t\t// answer describes a run nobody is watching any more.\n\t\t\t\tif (this.watchedRunUuid !== uuid) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tconst run = response.data || null\n\t\t\t\tthis.watchedRun = run\n\n\t\t\t\tconst log = Array.isArray(run?.log) ? run.log : []\n\t\t\t\tthis.watchedNewFrom = this.watchedSteps.length\n\t\t\t\tif (log.length > this.watchedSteps.length) {\n\t\t\t\t\tthis.watchedSteps = [\n\t\t\t\t\t\t...this.watchedSteps,\n\t\t\t\t\t\t...log.slice(this.watchedSteps.length),\n\t\t\t\t\t]\n\t\t\t\t}\n\n\t\t\t\tif (run !== null && FLOW_RUN_ACTIVE_STATUSES.includes(run.status) === false) {\n\t\t\t\t\tthis.stopWatching()\n\n\t\t\t\t\t// The Runs tab lists this run with the status it had when\n\t\t\t\t\t// the list was last read — usually `queued`. Refresh so the\n\t\t\t\t\t// history agrees with the canvas about how it ended.\n\t\t\t\t\tif (this.flow.id) {\n\t\t\t\t\t\tthis.loadRuns(this.flow.id)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not read the watched run', error)\n\n\t\t\t\t// A missing run will not come back; anything else (a blip, a\n\t\t\t\t// timeout) is worth the next poll.\n\t\t\t\tif (error?.response?.status === 404) {\n\t\t\t\t\tthis.stopWatching()\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Stop polling. The watched run and its steps are KEPT — the canvas's\n\t\t * final paint reads them — only the loop and its listener go.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tstopWatching() {\n\t\t\tthis.clearWatchTimer()\n\n\t\t\tif (this._watchOnVisibility !== undefined && this._watchOnVisibility !== null) {\n\t\t\t\tdocument.removeEventListener('visibilitychange', this._watchOnVisibility)\n\t\t\t\tthis._watchOnVisibility = null\n\t\t\t}\n\n\t\t\tthis.watching = false\n\t\t},\n\n\t\t/**\n\t\t * Pause the poll while the tab is hidden; refetch once and resume when\n\t\t * it comes back, so returning shows current state rather than whatever\n\t\t * was true when the tab was backgrounded.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tonWatchVisibilityChange() {\n\t\t\tif (document.hidden === true) {\n\t\t\t\tthis.clearWatchTimer()\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (this.watching !== true) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.fetchWatchedRun()\n\t\t\tthis.startWatchTimer()\n\t\t},\n\n\t\t/**\n\t\t * Ask the canvas to replay the inspected run's stored log.\n\t\t *\n\t\t * The steps are already here — `inspectRun()` fetched them — so this\n\t\t * only raises the token the canvas half watches. A live watch is\n\t\t * stopped first: a replay and a live run cannot share the canvas.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\trequestReplay() {\n\t\t\tif (!this.inspectedRunUuid || this.steps.length === 0) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.stopWatching()\n\t\t\tthis.replayUuid = this.inspectedRunUuid\n\t\t\tthis.replayToken += 1\n\t\t},\n\n\t\t/**\n\t\t * Load the last run and the runs-since count of each listed flow.\n\t\t *\n\t\t * One request for the whole list. A failure leaves the summary empty,\n\t\t * so the cells read \"never run\" rather than stale numbers.\n\t\t *\n\t\t * @param {Array<string>} flowIds The flows to summarise.\n\t\t * @param {string} since ISO 8601 moment the count starts at.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync loadRunSummary(flowIds, since) {\n\t\t\tconst ids = (flowIds || []).filter(Boolean)\n\t\t\tif (ids.length === 0) {\n\t\t\t\tthis.runSummary = {}\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst response = await axios.get(generateUrl('/apps/openregister/api/flow-runs/summary'), {\n\t\t\t\t\tparams: { flowIds: ids.join(','), since },\n\t\t\t\t})\n\t\t\t\tthis.runSummary = response.data?.results || {}\n\t\t\t} catch (error) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not load the run summary', error)\n\t\t\t\tthis.runSummary = {}\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Load the runs of the given flows since a moment, newest first.\n\t\t *\n\t\t * @param {Array<string>} flowIds The flows whose runs to list.\n\t\t * @param {string} since ISO 8601 moment the list starts at.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync loadRecentRuns(flowIds, since) {\n\t\t\tconst ids = (flowIds || []).filter(Boolean)\n\t\t\tif (ids.length === 0) {\n\t\t\t\tthis.recentRuns = []\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.recentRunsLoading = true\n\t\t\ttry {\n\t\t\t\tconst response = await axios.get(generateUrl('/apps/openregister/api/flow-runs'), {\n\t\t\t\t\tparams: { flowIds: ids.join(','), since, limit: 200 },\n\t\t\t\t})\n\t\t\t\tthis.recentRuns = response.data?.results || []\n\t\t\t} catch (error) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not load recent runs', error)\n\t\t\t\tthis.recentRuns = []\n\t\t\t} finally {\n\t\t\t\tthis.recentRunsLoading = false\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Switch a stored flow on or off from a list, without opening it.\n\t\t *\n\t\t * Reads the stored flow and writes it back whole with only `enabled`\n\t\t * changed, the same round trip `duplicate()` makes: a partial body\n\t\t * would be read as a document without nodes. The list row is updated\n\t\t * in place from the answer, so the toggle does not reload the list.\n\t\t *\n\t\t * @param {string} id The flow id or uuid.\n\t\t * @param {boolean} enabled The new state.\n\t\t * @return {Promise<object>} The saved flow.\n\t\t */\n\t\tasync setEnabled(id, enabled) {\n\t\t\tconst current = await axios.get(generateUrl(`/apps/openregister/api/flows/${id}`))\n\t\t\tconst response = await axios.put(\n\t\t\t\tgenerateUrl(`/apps/openregister/api/flows/${id}`),\n\t\t\t\t{ ...(current.data || {}), enabled: enabled === true },\n\t\t\t)\n\t\t\tconst saved = response.data || {}\n\t\t\tconst now = typeof saved.enabled === 'boolean' ? saved.enabled : enabled === true\n\t\t\tthis.flows = this.flows.map((flow) => (\n\t\t\t\tString(flow.id) === String(id) || String(flow.uuid) === String(id)\n\t\t\t\t\t? { ...flow, enabled: now }\n\t\t\t\t\t: flow\n\t\t\t))\n\t\t\treturn saved\n\t\t},\n\n\t\t/**\n\t\t * Start a finished run again, as `POST /api/flow-runs/{uuid}/retry`.\n\t\t *\n\t\t * @param {string} uuid The run to retry.\n\t\t * @return {Promise<object|null>} The new run, or null without a uuid.\n\t\t */\n\t\tasync retryRun(uuid) {\n\t\t\tif (!uuid) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst response = await axios.post(generateUrl(`/apps/openregister/api/flow-runs/${encodeURIComponent(uuid)}/retry`))\n\t\t\tif (this.flow.id) {\n\t\t\t\tawait this.loadRuns(this.flow.id)\n\t\t\t}\n\t\t\treturn response.data || null\n\t\t},\n\n\t\tasync loadRuns(flowId) {\n\t\t\ttry {\n\t\t\t\tconst response = await axios.get(generateUrl('/apps/openregister/api/flow-runs'), {\n\t\t\t\t\tparams: { flowId, limit: 25 },\n\t\t\t\t})\n\t\t\t\tthis.runs = response.data?.results || []\n\t\t\t} catch (error) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not load run history', error)\n\t\t\t\tthis.runs = []\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Load one run's per-node steps.\n\t\t *\n\t\t * This is what the step table exists for — the run's aggregate log\n\t\t * cannot answer \"which node produced this\" without being walked.\n\t\t *\n\t\t * @param {string} runUuid The run to inspect.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync inspectRun(runUuid) {\n\t\t\tthis.inspectedRunUuid = runUuid\n\t\t\tlet version = null\n\t\t\ttry {\n\t\t\t\tconst response = await axios.get(generateUrl(`/apps/openregister/api/flow-runs/${runUuid}`))\n\t\t\t\t// KEPT WHOLE, not picked apart. The record carries the run's\n\t\t\t\t// status, its error, and the objects it is about, none of which\n\t\t\t\t// can be recovered from the log or from the capped history list.\n\t\t\t\tthis.runDetail = response.data || null\n\t\t\t\tthis.steps = response.data?.log || []\n\t\t\t\t// Read from the RUN, not from `this.runs`. A run reached by\n\t\t\t\t// `?run=` need not be in the loaded page of run history at all —\n\t\t\t\t// the history is capped at 25 — and the run's own record is the\n\t\t\t\t// authority on which version of the flow it executed.\n\t\t\t\tversion = response.data?.flowVersion ?? null\n\t\t\t} catch (error) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not load the run steps', error)\n\t\t\t\tthis.runDetail = null\n\t\t\t\tthis.steps = []\n\t\t\t}\n\n\t\t\t// BEFORE the objects and tasks: those two only fill panels, while\n\t\t\t// this changes what the canvas is showing, and a reader watching the\n\t\t\t// graph swap after the panels have settled reads it as a glitch.\n\t\t\tawait this.showRunVersionGraph(version)\n\n\t\t\t// Loaded alongside the steps, not on demand behind another click.\n\t\t\t// The steps say what the run DID; these say what it did it TO, and\n\t\t\t// reading one without the other is the gap this exists to close.\n\t\t\tawait this.loadRunObjects(runUuid)\n\t\t\tawait this.loadRunTasks(runUuid)\n\t\t},\n\n\t\t/**\n\t\t * Put the graph a run actually executed onto the canvas.\n\t\t *\n\t\t * The version's stored graph replaces `flow.nodes`/`flow.edges` for as\n\t\t * long as the run is open. The displaced graph is stashed in `liveGraph`\n\t\t * so `closeRun()` can put it back exactly — refetching instead would\n\t\t * lose an author's in-progress layout for no gain.\n\t\t *\n\t\t * 🔴 UNSAVED WORK IS NEVER DISPLACED. `dirty` means the author has edits\n\t\t * on this canvas that exist nowhere else. Swapping the graph out from\n\t\t * under them would destroy those edits with no undo and no warning, to\n\t\t * show a nicety. So a dirty canvas keeps its graph and the run replays\n\t\t * over it, exactly as it did before this existed, and CnFlowDetail says\n\t\t * so on the canvas rather than leaving the reader to guess which graph\n\t\t * they are looking at.\n\t\t *\n\t\t * A version that cannot be read — pruned, or never recorded for a run\n\t\t * from before versioning — is recorded in `runGraphNotice` and\n\t\t * the replay falls back to the live graph. That fallback is the OLD\n\t\t * behaviour, so nothing regresses; it just stops being silent.\n\t\t *\n\t\t * @param {number|string|null} version The run's `flowVersion`.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync showRunVersionGraph(version) {\n\t\t\tthis.runGraphNotice = null\n\n\t\t\tconst number = Number(version)\n\t\t\tif (!this.flow.id || !Number.isInteger(number) || number <= 0) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (this.dirty === true) {\n\t\t\t\tthis.runGraphNotice = { version: number, reason: 'unsaved-edits' }\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst response = await axios.get(generateUrl(`/apps/openregister/api/flows/${this.flow.id}/versions/${number}`))\n\t\t\t\tconst graph = response.data?.graph\n\t\t\t\tif (!graph || Array.isArray(graph.nodes) === false) {\n\t\t\t\t\tthis.runGraphNotice = { version: number, reason: 'unreadable' }\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// Stashed ONCE. Moving between two runs of the same flow calls\n\t\t\t\t// this twice, and overwriting the stash on the second call would\n\t\t\t\t// store the FIRST run's snapshot as the live graph — after\n\t\t\t\t// which closing the run restores a version instead of the flow.\n\t\t\t\tif (this.liveGraph === null) {\n\t\t\t\t\tthis.liveGraph = {\n\t\t\t\t\t\tnodes: this.flow.nodes,\n\t\t\t\t\t\tedges: this.flow.edges,\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tthis.flow = {\n\t\t\t\t\t...this.flow,\n\t\t\t\t\t// Deep-copied for the same reason `open()` deep-copies the\n\t\t\t\t\t// list row: the canvas mutates node positions, and a stored\n\t\t\t\t\t// version is not the place to discover that.\n\t\t\t\t\tnodes: JSON.parse(JSON.stringify(graph.nodes)),\n\t\t\t\t\tedges: Array.isArray(graph.edges) ? JSON.parse(JSON.stringify(graph.edges)) : [],\n\t\t\t\t}\n\t\t\t\tthis.viewingVersion = number\n\n\t\t\t\t// A stored version carries whatever coordinates it was saved\n\t\t\t\t// with, and a flow imported from `x-openregister-flows` was\n\t\t\t\t// saved with none — so the same pile `open()` guards against\n\t\t\t\t// arrives here by a different route.\n\t\t\t\tthis.applyRenderLayout()\n\t\t\t} catch (error) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not read the graph this run executed', error)\n\t\t\t\tthis.runGraphNotice = { version: number, reason: 'unreadable' }\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Stop inspecting a run and put the live graph back.\n\t\t *\n\t\t * The one way out, so the restore cannot be forgotten. Setting\n\t\t * `inspectedRunUuid = null` by hand would leave a historic graph on a\n\t\t * canvas that no longer says it is historic — and, because the lock\n\t\t * lifts with `viewingVersion`, an editable one.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tcloseRun() {\n\t\t\tthis.inspectedRunUuid = null\n\t\t\tthis.runDetail = null\n\t\t\t// The other half of run view. Leaving it set would keep every\n\t\t\t// surface in run view after the reader asked to go back to the flow,\n\t\t\t// and the canvas would keep saying the run was still opening.\n\t\t\tthis.openingRunUuid = null\n\t\t\tthis.steps = []\n\t\t\tthis.runObjects = []\n\t\t\tthis.runTasks = []\n\t\t\tthis.replayUuid = null\n\t\t\tthis.runGraphNotice = null\n\n\t\t\tif (this.liveGraph !== null) {\n\t\t\t\tthis.flow = {\n\t\t\t\t\t...this.flow,\n\t\t\t\t\tnodes: this.liveGraph.nodes,\n\t\t\t\t\tedges: this.liveGraph.edges,\n\t\t\t\t}\n\t\t\t\tthis.liveGraph = null\n\t\t\t}\n\n\t\t\tthis.viewingVersion = null\n\t\t},\n\n\t\t/**\n\t\t * Load the tasks one run raised.\n\t\t *\n\t\t * 🔴 AN EMPTY UUID IS NOT A QUERY, AND THE SERVER WILL NOT SAVE US.\n\t\t * `?runUuid=` is treated as ABSENT, and an absent anchor means the\n\t\t * endpoint answers with the caller's ordinary inbox. Sending one would\n\t\t * put somebody's own task list under a run's Tasks tab, so the guard is\n\t\t * here rather than a hope that an empty answer comes back.\n\t\t *\n\t\t * 🔴 THE RESPONSE IS CHECKED AGAINST THE RUN, NOT TRUSTED. The anchor\n\t\t * is merged (openregister `801cc02b`), but this is a LIBRARY: a\n\t\t * consuming app can be running an openregister from before it, where an\n\t\t * unknown query parameter is silently dropped rather than rejected. That\n\t\t * server returns a perfectly valid 200 full of the reader's own tasks,\n\t\t * and rendering it would be a disclosure dressed as a feature with\n\t\t * nothing failing anywhere. Rows that do not name this run are dropped;\n\t\t * against an old server that empties the tab, which is the honest\n\t\t * answer.\n\t\t *\n\t\t * `scope` is deliberately NOT sent. The anchor overrides it, so passing\n\t\t * one would be a parameter that reads as though it narrowed something.\n\t\t *\n\t\t * @param {string} runUuid The run to read.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync loadRunTasks(runUuid) {\n\t\t\tif (!runUuid) {\n\t\t\t\tthis.runTasks = []\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst response = await axios.get(generateUrl('/apps/openregister/api/flow-tasks'), {\n\t\t\t\t\tparams: { runUuid },\n\t\t\t\t})\n\n\t\t\t\tconst rows = response.data?.results || []\n\t\t\t\tthis.runTasks = rows.filter((task) => String(task?.runUuid || '') === String(runUuid))\n\t\t\t} catch (error) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not load the tasks this run raised', error)\n\t\t\t\tthis.runTasks = []\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Load the objects one run touched, grouped by the node that touched them.\n\t\t *\n\t\t * A run's own record names only the object that TRIGGERED it, so\n\t\t * everything it went on to create or change is answerable only from the\n\t\t * attribution stamped on the audit trail. This is that read.\n\t\t *\n\t\t * Failure is quiet and empties the list rather than leaving the previous\n\t\t * run's objects on screen — stale rows here would be read as \"this run\n\t\t * touched those\", which is worse than showing nothing.\n\t\t *\n\t\t * @param {string} runUuid The run to read.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync loadRunObjects(runUuid) {\n\t\t\ttry {\n\t\t\t\tconst response = await axios.get(generateUrl(`/apps/openregister/api/flow-runs/${runUuid}/objects`))\n\t\t\t\tthis.runObjects = response.data?.nodes || []\n\t\t\t} catch (error) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not load the objects this run touched', error)\n\t\t\t\tthis.runObjects = []\n\t\t\t}\n\t\t},\n\t},\n})\n"],"names":["axios","t"],"mappings":";;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAC;AAClE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACY,MAAC,wBAAwB,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAC;AAC1E;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,yBAAyB,GAAG,KAAI;AACtC,MAAM,uBAAuB,GAAG,KAAI;AACpC;AACA,SAAS,SAAS,GAAG;AACrB,CAAC,OAAO;AACR,EAAE,IAAI,EAAE,EAAE;AACV,EAAE,WAAW,EAAE,EAAE;AACjB,EAAE,KAAK,EAAE,EAAE;AACX,EAAE,GAAG,EAAE,cAAc;AACrB,EAAE,eAAe,EAAE,EAAE;AACrB,EAAE,aAAa,EAAE,EAAE;AACnB,EAAE,OAAO,EAAE,gBAAgB;AAC3B,EAAE,IAAI,EAAE,EAAE;AACV,EAAE,aAAa,EAAE,OAAO;AACxB,EAAE,OAAO,EAAE,KAAK;AAChB,EAAE,KAAK,EAAE,EAAE;AACX,EAAE,KAAK,EAAE,EAAE;AACX,EAAE,MAAM,EAAE,EAAE;AACZ,EAAE,aAAa,EAAE,IAAI;AACrB,EAAE,YAAY,EAAE,IAAI;AACpB,EAAE,gBAAgB,EAAE,IAAI;AACxB;AACA;AACA;AACA;AACA,EAAE,OAAO,EAAE,CAAC;AACZ,EAAE,eAAe,EAAE,OAAO;AAC1B,EAAE;AACF,CAAC;AACD;AACY,MAAC,YAAY,GAAG,WAAW,CAAC,QAAQ,EAAE;AAClD,CAAC,KAAK,EAAE,OAAO;AACf,EAAE,IAAI,EAAE,SAAS,EAAE;AACnB,EAAE,KAAK,EAAE,EAAE;AACX;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAE,SAAS,EAAE,EAAE;AACf,EAAE,cAAc,EAAE,IAAI;AACtB,EAAE,eAAe,EAAE,IAAI;AACvB;AACA;AACA;AACA;AACA,EAAE,aAAa,EAAE,IAAI;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAE,WAAW,EAAE,IAAI;AACnB;AACA;AACA;AACA;AACA;AACA;AACA,EAAE,kBAAkB,EAAE,IAAI;AAC1B;AACA;AACA;AACA;AACA,EAAE,WAAW,EAAE,IAAI;AACnB;AACA;AACA,EAAE,QAAQ,EAAE,EAAE;AACd;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAE,gBAAgB,EAAE,IAAI;AACxB;AACA;AACA,EAAE,aAAa,EAAE,KAAK;AACtB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAE,cAAc,EAAE,IAAI;AACtB;AACA;AACA,EAAE,iBAAiB,EAAE,KAAK;AAC1B;AACA;AACA;AACA;AACA,EAAE,kBAAkB,EAAE,IAAI;AAC1B;AACA;AACA;AACA;AACA,EAAE,WAAW,EAAE,EAAE;AACjB,EAAE,YAAY,EAAE,EAAE;AAClB;AACA;AACA;AACA;AACA;AACA,EAAE,cAAc,EAAE,KAAK;AACvB;AACA;AACA;AACA,EAAE,UAAU,EAAE,EAAE;AAChB;AACA;AACA;AACA,EAAE,UAAU,EAAE,EAAE;AAChB,EAAE,iBAAiB,EAAE,KAAK;AAC1B;AACA;AACA;AACA,EAAE,IAAI,EAAE,EAAE;AACV,EAAE,KAAK,EAAE,EAAE;AACX;AACA;AACA;AACA;AACA,EAAE,UAAU,EAAE,EAAE;AAChB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAE,QAAQ,EAAE,EAAE;AACd,EAAE,gBAAgB,EAAE,IAAI;AACxB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAE,SAAS,EAAE,IAAI;AACjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAC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"}
|
|
1
|
+
{"version":3,"file":"useFlowStore.js","sources":["../../../src/composables/useFlowStore.js"],"sourcesContent":["// SPDX-License-Identifier: EUPL-1.2\n// Copyright (C) 2026 Conduction B.V.\n//\n// Shared state for the flow editor.\n//\n// The canvas (CnFlowDetail) and the controls (CnFlowSidebar) render in two\n// different places — the page body and Nextcloud's app sidebar — so they cannot\n// pass props to one another. The flow being edited lives here instead.\n//\n// Ported from hermiq's `graphEditor` store, which was the fleet's only flow\n// editor. Two things changed in the port:\n//\n// 1. Persistence is OpenRegister's ONE flow store (`/api/flows`), not an app's\n// own register. That is the whole point of the unification: hermiq kept\n// flows as `agentflow` objects, so every app that wanted flows needed its\n// own register, its own resolver and — in practice — its own executor.\n// 2. Node types are the catalogue's ids, VERBATIM. hermiq's builder fed its\n// palette from the catalogue (namespaced: `openregister.set-fields`,\n// `hermiq.agent-step`) while its config panes and its executor matched\n// BARE ids (`set-fields`, `agent-step`). Every node placed from the palette\n// therefore had no config pane and was skipped at run time — silently, with\n// the run reporting success. Nothing here may reintroduce a second\n// vocabulary.\n\nimport axios from '@nextcloud/axios'\nimport { translate as t } from '@nextcloud/l10n'\nimport { generateUrl } from '@nextcloud/router'\nimport { defineStore } from 'pinia'\nimport { layoutFlowNodes, needsFullLayout, placeLooseNodes } from './flowGraphLayout.js'\nimport { DEFAULT_EDGE_LINE_TYPE } from './useFlowEdgeStyles.js'\n\n/**\n * A blank flow definition.\n *\n * @return {object} The empty flow.\n */\n/**\n * The fields that make up the pinned DEFINITION of a flow.\n *\n * Kept in step with `FlowDefinitionPin::PINNED_KEYS` on the server: these four\n * are what a version's hash is taken over, so these four are what a published\n * version refuses to have changed.\n *\n * @type {string[]}\n */\nconst GRAPH_FIELDS = ['nodes', 'edges', 'limits', 'executionMode']\n\n/**\n * The run statuses the engine treats as \"still going\".\n *\n * Mirrors `FlowRun::ACTIVE` on the server (`queued`, `running`, `suspended`);\n * everything else (`completed`, `stopped`, `failed`, `dead_letter`) is\n * terminal. The watcher polls while a run is in this set and stops by itself\n * the moment it leaves it.\n *\n * @type {string[]}\n */\nexport const FLOW_RUN_ACTIVE_STATUSES = ['queued', 'running', 'suspended']\n\n/**\n * How often the watched run is polled, and the floor under a caller-supplied\n * interval.\n *\n * 3s because the editor's Run is interactive — a person is looking — so the\n * dashboard widget's 15s feels dead; floored at 2s because the engine writes\n * the log once per worker pass, so polling faster multiplies requests for no\n * extra information.\n */\nconst WATCH_INTERVAL_DEFAULT_MS = 3000\nconst WATCH_INTERVAL_FLOOR_MS = 2000\n\nfunction emptyFlow() {\n\treturn {\n\t\tname: '',\n\t\tdescription: '',\n\t\tnotes: '',\n\t\tapp: 'openregister',\n\t\ttriggerRegister: '',\n\t\ttriggerSchema: '',\n\t\ttrigger: 'object.updated',\n\t\tcron: '',\n\t\texecutionMode: 'async',\n\t\tenabled: false,\n\t\tnodes: [],\n\t\tedges: [],\n\t\tlimits: {},\n\t\tretentionDays: null,\n\t\tauditEnabled: null,\n\t\toversightEnabled: null,\n\n\t\t// A new flow is a DRAFT. Nothing runs it until it is published, which\n\t\t// is the point: an author builds a graph over several sittings and a\n\t\t// half-wired process must not be firing on object writes in between.\n\t\tversion: 1,\n\t\tlifecycleStatus: 'draft',\n\t}\n}\n\nexport const useFlowStore = defineStore('cnFlow', {\n\tstate: () => ({\n\t\tflow: emptyFlow(),\n\t\tflows: [],\n\n\t\t// How the automatic layout runs: `right` (left to right) or `down`\n\t\t// (top to bottom). Set by the editor that hosts the canvas.\n\t\tlayoutDirection: 'right',\n\n\t\t// Snapshots of `flow`, oldest first, for Ctrl+Z.\n\t\t//\n\t\t// A canvas is direct manipulation: a mis-drag or a mis-aimed Delete\n\t\t// destroys work with no dialog in between, and until this existed the\n\t\t// only way back was to reload and lose everything since the last save.\n\t\t// The stack is capped — see pushUndo() — because a flow document is\n\t\t// held whole in each entry.\n\t\tundoStack: [],\n\t\tselectedNodeId: null,\n\t\tpaletteDragType: null,\n\n\t\t// The node whose edit dialog is open, or null. Lives here because the\n\t\t// dialog is hosted by the canvas while it is opened from the sidebar,\n\t\t// a node double-click, or a consumer.\n\t\teditingNodeId: null,\n\n\t\t// The CONNECTION whose edit dialog is open, as `{source, target}`, or\n\t\t// null.\n\t\t//\n\t\t// ⚠️ NOT AN ID. `canvasEdges` expands one stored edge into several drawn\n\t\t// lines — `{from: 'a', to: ['b', 'c']}` is two lines — so a line's id is\n\t\t// synthesised per render and means nothing to the document. The endpoint\n\t\t// pair is the only thing that identifies a line in both worlds, and it\n\t\t// is what every edge action below is keyed on.\n\t\teditingEdge: null,\n\n\t\t// The label and router copied off a line, for pasting onto another. A\n\t\t// line has no meaningful duplicate — two identical `from`/`to` records\n\t\t// draw on top of each other and the engine dedupes them — so Copy on a\n\t\t// connection copies its PRESENTATION, which is the part that is actually\n\t\t// worth repeating across a graph.\n\t\tedgeStyleClipboard: null,\n\n\t\t// Whether the controls sidebar is shown. Lives here because the\n\t\t// re-open affordance sits on the canvas toolbar, in the other half of\n\t\t// the tree.\n\t\tsidebarOpen: true,\n\n\t\t// Every version of the open flow, newest first.\n\t\tversions: [],\n\n\t\t// The server's last lifecycle refusal, as `{reason, lifecycleStatus}`.\n\t\t//\n\t\t// 🔑 KEPT AS THE SERVER'S FIELDS, not as a rendered sentence. \"this\n\t\t// version is published, create a draft\" and \"this flow has no published\n\t\t// version, publish one\" want opposite buttons, and choosing between\n\t\t// them by matching on message text is how a UI offers the wrong one.\n\t\tlifecycleRefusal: null,\n\n\t\t// Whether a lifecycle transition is in flight.\n\t\ttransitioning: false,\n\n\t\t// What publishing WOULD do, as the server answered it: the next\n\t\t// semantic version, and when major, what the publish takes away.\n\t\t//\n\t\t// 🔑 THE SERVER'S ANSWER, NOT A SECOND OPINION. Deriving \"this looks\n\t\t// breaking\" in the client would be a second implementation of the rule,\n\t\t// and the first time the two disagree the author learns to believe\n\t\t// neither.\n\t\tpublishPreview: null,\n\n\t\t// Whether that preview is being fetched.\n\t\tpreviewingPublish: false,\n\n\t\t// The server's refusal of an explicit bump, as a sentence naming what\n\t\t// was removed. Separate from `lifecycleRefusal`: the flow's state is\n\t\t// fine, the REQUEST is what was wrong.\n\t\tversionBumpRefusal: null,\n\n\t\t// The node types the engine can actually execute. The catalogue is\n\t\t// AUTHORITATIVE: a builder that invents its own ids produces flows the\n\t\t// engine cannot run, which is exactly the defect this replaces.\n\t\tnodeCatalog: [],\n\t\teventCatalog: [],\n\n\t\t// Whether the catalogue request is still in flight. Without this flag\n\t\t// the palette cannot tell \"loading\" from \"failed\": both are an empty\n\t\t// list, and the sidebar showed \"Could not read the flow engine's node\n\t\t// types\" on every fresh /flows/new while the request was mid-air.\n\t\tcatalogLoading: false,\n\n\t\t// Per flow id: `{ lastRun, runsSince }` from `GET /api/flow-runs/summary`,\n\t\t// the read behind a flow list's last-run and runs-this-week columns.\n\t\trunSummary: {},\n\t\t// The runs of every listed flow since `runSummarySince`, for a\n\t\t// \"runs this week\" list. Separate from `runs`, which belongs to the\n\t\t// flow open in the editor.\n\t\trecentRuns: [],\n\t\trecentRunsLoading: false,\n\n\t\t// The runs of the flow being edited, and the per-node steps of the run\n\t\t// currently being inspected.\n\t\truns: [],\n\t\tsteps: [],\n\t\t// What the inspected run TOUCHED, grouped by node. Distinct from\n\t\t// `steps`, which is what it did: a step that wrote nothing still has a\n\t\t// step row, and an object written by an app the node called into has no\n\t\t// step of its own.\n\t\trunObjects: [],\n\t\t// The tasks THIS RUN raised, from `GET /api/flow-tasks?runUuid={uuid}`.\n\t\t//\n\t\t// The parameter ANCHORS the read rather than filtering it: with it\n\t\t// present the server ignores `scope`, so these are the run's tasks and\n\t\t// not the reader's inbox. Visibility still applies on top, so a caller\n\t\t// who is neither the run's requester nor an admin can see fewer rows\n\t\t// than the run has. That is correct, and nothing here works around it.\n\t\trunTasks: [],\n\t\tinspectedRunUuid: null,\n\n\t\t// THE INSPECTED RUN'S OWN RECORD, as the server answered it.\n\t\t//\n\t\t// `runs` is the flow's run history and it is capped at 25, so a run\n\t\t// reached by `?run=` need not be in it at all. Reading the header from\n\t\t// that list alone left a deep-linked run with no status, no time and no\n\t\t// error, which reads as a run that recorded nothing.\n\t\t//\n\t\t// It also carries what `GET /flow-runs/{uuid}/objects` cannot: the\n\t\t// objects the run is ABOUT (`subjects`) and the ones it is holding at a\n\t\t// place (`placeItems`). That endpoint reports audited CHANGES, so a run\n\t\t// that waited on a locked object and failed lists nothing there while\n\t\t// its own error names that object.\n\t\trunDetail: null,\n\n\t\t// THE GRAPH AS IT RAN, not the graph as it is now.\n\t\t//\n\t\t// A run records the `flowVersion` it executed, and a flow's graph moves\n\t\t// on: steps are added, renamed and deleted. Replaying an old run over\n\t\t// today's canvas paints badges onto nodes that were not there when it\n\t\t// ran and silently drops the ones that have since been deleted — the\n\t\t// `run-skipped` warning in CnFlowDetail exists solely to apologise for\n\t\t// that. So inspecting a run loads that version's stored graph and shows\n\t\t// it, and the reader is looking at what actually executed.\n\t\t//\n\t\t// `viewingVersion` is the version number on the canvas, or null for the\n\t\t// live graph. `liveGraph` is the graph that was displaced, kept so\n\t\t// closing the run restores it EXACTLY rather than refetching and hoping.\n\t\t// `runGraphNotice` is why the snapshot is NOT on the canvas when a run\n\t\t// is open, as `{ version, reason }`. There are two reasons and they are\n\t\t// not interchangeable: `unreadable` is a version row that could not be\n\t\t// fetched, and `unsaved-edits` is a canvas we refused to displace. Both\n\t\t// end with the replay drawn over the live graph, so without this the\n\t\t// reader cannot tell which graph they are looking at, and the answer\n\t\t// differs from the one the `viewingVersion` banner would have given.\n\t\tviewingVersion: null,\n\t\tliveGraph: null,\n\t\trunGraphNotice: null,\n\n\t\t// The run being WATCHED live: the one `run()` just queued, polled while\n\t\t// its status is non-terminal. The store exposes FACTS about it — the\n\t\t// run, its ordered steps, which of them are new since the last poll —\n\t\t// and animates nothing: the animation timeline lives in CnFlowDetail,\n\t\t// the only place that knows what a hop looks like. Splitting it this\n\t\t// way keeps the store testable without a clock.\n\t\twatchedRunUuid: null,\n\t\twatchedRun: null,\n\n\t\t// The watched run's log so far, in the engine's order. WITHIN ONE RUN\n\t\t// THE LOG ONLY GROWS — the engine appends per worker pass, and a\n\t\t// resumed pass appends after the `suspended` entry — so entries are\n\t\t// appended by index and an already-exposed step is never replaced or\n\t\t// replayed.\n\t\twatchedSteps: [],\n\n\t\t// Where the latest poll's NEW entries start in `watchedSteps`. The\n\t\t// index diff is exact because the log only grows; a consumer reads\n\t\t// `newWatchedSteps` to learn what arrived without replaying the rest.\n\t\twatchedNewFrom: 0,\n\n\t\t// Whether the poll loop is live. Stays true while the tab is hidden —\n\t\t// the timer is paused, not the watch — and turns false on a terminal\n\t\t// status, a re-watch, or teardown.\n\t\twatching: false,\n\n\t\t// A replay request for the INSPECTED run, as a monotonic token. The\n\t\t// sidebar raises it (`requestReplay()`), the canvas half watches it and\n\t\t// plays `steps` through its animator. A token rather than a flag so\n\t\t// replaying the same run twice in a row is two requests.\n\t\treplayUuid: null,\n\t\treplayToken: 0,\n\n\t\t// The flow LIST request, and nothing else. Read the comment below before\n\t\t// reaching for it as \"the editor is loading\": it is not.\n\t\tloading: false,\n\t\tsaving: false,\n\t\trunning: false,\n\t\tchecking: false,\n\n\t\t// 🔴 WHAT `loading` DOES NOT COVER, AND WHY A SECOND FLAG EXISTS.\n\t\t//\n\t\t// `loading` is set around `GET /api/flows` alone. The editor's arrival is\n\t\t// up to three requests deep: the list, then the run named by `?run=`,\n\t\t// then the stored graph that run executed. The canvas rendered\n\t\t// \"No steps yet\" through all of it, because `nodes.length === 0` is true\n\t\t// for a flow that has not arrived yet.\n\t\t//\n\t\t// An empty state that means \"still fetching\" is indistinguishable from\n\t\t// one that means \"this flow has no steps\", and only the second is an\n\t\t// answer. So `bootstrapping` spans the WHOLE arrival: the surface about\n\t\t// to make those requests raises it before the first one, and lowers it\n\t\t// when the last has settled.\n\t\tbootstrapping: false,\n\n\t\t// The run the URL named, from before it has been fetched.\n\t\t//\n\t\t// `inspectedRunUuid` is only set once `inspectRun()` runs, and that is\n\t\t// behind the flow load, so a visitor arriving on `/flows/x?run=y` saw\n\t\t// the full flow editor first and the run view a moment later, complete\n\t\t// with Add a step, Save and a sidebar telling them to save the flow.\n\t\t// The URL had already said a run was being viewed, so this records that\n\t\t// fact synchronously and `inRunView` reads both.\n\t\topeningRunUuid: null,\n\n\t\t// The engine's verdict on the unsaved canvas, from `check()`. Cleared\n\t\t// by any edit that could change it, so a stale \"looks runnable\" never\n\t\t// outlives the graph it described.\n\t\tcheckResult: null,\n\n\t\tdirty: false,\n\t\terror: null,\n\t\t/**\n\t\t * The flow id that could not be resolved, or null.\n\t\t *\n\t\t * Distinct from `error`, which is a failed REQUEST. A flow that resolves\n\t\t * to nothing is a successful request with an empty answer, and the canvas\n\t\t * must be able to tell a reader that rather than rendering an empty grid\n\t\t * that looks like a flow with no steps.\n\t\t */\n\t\tnotFound: null,\n\t}),\n\n\tgetters: {\n\t\tnodes: (state) => state.flow.nodes || [],\n\t\tedges: (state) => state.flow.edges || [],\n\n\t\t/**\n\t\t * Whether this flow runs inline rather than through the worker.\n\t\t *\n\t\t * The engine's own vocabulary is `sync` / `async` on the flow, and the\n\t\t * default is async — so anything the API has not told us about, or has\n\t\t * not set, queues. Reading it here rather than at the call site keeps\n\t\t * the one place that knows the vocabulary.\n\t\t *\n\t\t * @param {object} state The store state.\n\t\t * @return {boolean} True when a run should be executed immediately.\n\t\t */\n\t\trunsSynchronously: (state) => String(state.flow.executionMode || '').toLowerCase() === 'sync',\n\n\t\t/**\n\t\t * @param {object} state The store state.\n\t\t * @return {string} The open flow's lifecycle status.\n\t\t */\n\t\tlifecycleStatus: (state) => state.flow.lifecycleStatus || 'draft',\n\n\t\t/**\n\t\t * @param {object} state The store state.\n\t\t * @return {number} The open flow's version number.\n\t\t */\n\t\tflowVersion: (state) => Number(state.flow.version || 1),\n\n\t\t/**\n\t\t * What the version pill says: the semantic version where the engine\n\t\t * has derived one, the ordinal where it has not.\n\t\t *\n\t\t * A flow that has never been published has no semantic version, and a\n\t\t * draft has none either — it has not been compared with anything yet.\n\t\t * Showing `v0.0.0` there would be a claim; showing the ordinal is the\n\t\t * truth the flow actually carries.\n\t\t *\n\t\t * @param {object} state The store state.\n\t\t * @return {string} The label, without a leading `v`.\n\t\t */\n\t\tflowVersionLabel: (state) => {\n\t\t\tconst semver = String(state.flow.semver || '').trim()\n\n\t\t\treturn (semver === '') ? String(Number(state.flow.version || 1)) : semver\n\t\t},\n\n\t\t/**\n\t\t * @param {object} state The store state.\n\t\t * @return {boolean} Whether the open flow is a draft.\n\t\t */\n\t\tisDraft: (state) => (state.flow.lifecycleStatus || 'draft') === 'draft',\n\n\t\t/**\n\t\t * @param {object} state The store state.\n\t\t * @return {boolean} Whether the open flow is published.\n\t\t */\n\t\tisPublished: (state) => state.flow.lifecycleStatus === 'published',\n\n\t\t/**\n\t\t * Whether the GRAPH may not be edited.\n\t\t *\n\t\t * 🔴 THE GRAPH, NOT THE FLOW. A published version's nodes and edges are\n\t\t * immutable, but its name, description and enabled flag are not —\n\t\t * renaming a live process or switching it off are not changes to the\n\t\t * process. The server draws the line in exactly the same place, so an\n\t\t * editor that locked everything would refuse edits the API accepts.\n\t\t *\n\t\t * 🔴 A VERSION SNAPSHOT IS LOCKED TOO, AND THIS IS NOT COSMETIC.\n\t\t *\n\t\t * `viewingVersion` means the canvas holds a HISTORIC graph loaded for a\n\t\t * run replay, while `flow.id` still names the live flow. `save()` picks\n\t\t * PUT over POST from `flow.id`, so a single edit-and-save on a snapshot\n\t\t * would overwrite the current flow with an old graph — the same class of\n\t\t * loss the `id` watcher in CnFlowDetail was written to prevent, reached\n\t\t * by a different door. Reusing the existing lock rather than inventing a\n\t\t * read-only mode means every caller that already respects `graphLocked`\n\t\t * — `pushUndo()` and everything gated behind it — is correct here for\n\t\t * free, and a new call site cannot forget the snapshot case.\n\t\t *\n\t\t * @param {object} state The store state.\n\t\t * @return {boolean} Whether graph edits are locked.\n\t\t */\n\t\tgraphLocked: (state) => state.viewingVersion !== null\n\t\t\t|| ['published', 'deprecated'].includes(state.flow.lifecycleStatus),\n\n\t\t/**\n\t\t * Whether the surfaces are showing a RUN rather than the flow.\n\t\t *\n\t\t * 🔑 TWO SOURCES, AND THE EARLY ONE IS THE POINT. `inspectedRunUuid` is\n\t\t * the run that has been read; `openingRunUuid` is the run the URL named,\n\t\t * known before anything is fetched. Reading only the first meant the\n\t\t * editor spent the whole load in flow-edit mode with the address bar\n\t\t * already saying otherwise, so the reader was offered Add a step, Save\n\t\t * and Run on a page that was about to become read-only.\n\t\t *\n\t\t * @param {object} state The store state.\n\t\t * @return {boolean} True while a run is open or being opened.\n\t\t */\n\t\tinRunView: (state) => Boolean(state.inspectedRunUuid) || state.openingRunUuid !== null,\n\n\t\t/**\n\t\t * Whether the canvas is still waiting for the graph it is going to show.\n\t\t *\n\t\t * The one flag a canvas should ask, rather than assembling it from\n\t\t * `loading` plus two run flags at every call site: any of the three\n\t\t * requests behind the first paint being in the air means the graph on\n\t\t * screen is not yet an answer.\n\t\t *\n\t\t * @param {object} state The store state.\n\t\t * @return {boolean} True while the graph is still being fetched.\n\t\t */\n\t\tcanvasLoading: (state) => state.bootstrapping === true || state.openingRunUuid !== null,\n\n\t\t/**\n\t\t * Whether there is anything to undo. Drives the toolbar's disabled state.\n\t\t *\n\t\t * @param {object} state The store state.\n\t\t * @return {boolean} True when the stack holds at least one snapshot.\n\t\t */\n\t\tcanUndo: (state) => state.undoStack.length > 0,\n\n\t\tselectedNode: (state) => {\n\t\t\tif (state.selectedNodeId === null) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\treturn (state.flow.nodes || []).find((n) => n.id === state.selectedNodeId) || null\n\t\t},\n\n\t\t/**\n\t\t * The node whose edit dialog is open, or null.\n\t\t *\n\t\t * @param {object} state The store state.\n\t\t * @return {object|null} The node.\n\t\t */\n\t\teditingNode: (state) => {\n\t\t\tif (state.editingNodeId === null) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\treturn (state.flow.nodes || []).find((n) => n.id === state.editingNodeId) || null\n\t\t},\n\n\t\t/**\n\t\t * The catalogue entry for a node type, or null when the engine does not\n\t\t * know it.\n\t\t *\n\t\t * A null here is meaningful and must be SHOWN, not hidden: it means the\n\t\t * flow carries a node the engine cannot resolve, which will fail its\n\t\t * step at run time.\n\t\t *\n\t\t * @param {object} state The store state.\n\t\t * @return {(type: string) => object|null} The catalogue entry, or null when the engine does not know the type.\n\t\t */\n\t\tcatalogEntry: (state) => (type) => {\n\t\t\treturn state.nodeCatalog.find((entry) => (\n\t\t\t\tentry.id === type || (entry.aliases || []).includes(type)\n\t\t\t)) || null\n\t\t},\n\n\t\t/**\n\t\t * A node type's role — `trigger`, `step` or `end` — from the catalogue.\n\t\t *\n\t\t * Falls back to the id's naming convention only while the catalogue has\n\t\t * not loaded, so the canvas is not colourless during the first paint.\n\t\t *\n\t\t * @return {(type: string) => 'trigger'|'step'|'end'} The role of a node type.\n\t\t */\n\t\troleOfNodeType() {\n\t\t\treturn (type) => {\n\t\t\t\tconst entry = this.catalogEntry(type)\n\t\t\t\tif (entry?.role) {\n\t\t\t\t\treturn entry.role\n\t\t\t\t}\n\n\t\t\t\tconst id = String(type || '')\n\t\t\t\tif (id.includes('.trigger-')) {\n\t\t\t\t\treturn 'trigger'\n\t\t\t\t}\n\t\t\t\tif (id.endsWith('.end') || id.endsWith('.stop')) {\n\t\t\t\t\treturn 'end'\n\t\t\t\t}\n\n\t\t\t\treturn 'step'\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * The edges as the canvas draws them: one line per (source, target)\n\t\t * pair, whatever dialect the stored flow speaks.\n\t\t *\n\t\t * This store writes `{from, to}` — the ONLY dialect the engine reads —\n\t\t * but it must still DRAW `{source, target}`, which older documents and\n\t\t * hermiq's flows carry. Each endpoint\n\t\t * may be a LIST (several `from` = join, several `to` = split). Handing\n\t\t * `flow.edges` to the canvas raw therefore rendered every one of those\n\t\t * flows as unconnected cards: real graphs, silently drawn wrong.\n\t\t *\n\t\t * @param {object} state The store state.\n\t\t * @return {Array<object>} Drawable `{id, source, target, edge}` lines.\n\t\t */\n\t\tcanvasEdges: (state) => {\n\t\t\tconst toList = (value) => {\n\t\t\t\tif (Array.isArray(value)) {\n\t\t\t\t\treturn value.filter((v) => v !== null && v !== undefined && v !== '')\n\t\t\t\t}\n\n\t\t\t\treturn (value === null || value === undefined || value === '') ? [] : [value]\n\t\t\t}\n\n\t\t\tconst lines = []\n\t\t\tfor (const [index, edge] of (state.flow.edges || []).entries()) {\n\t\t\t\tconst sources = toList(edge.source ?? edge.from)\n\t\t\t\tconst targets = toList(edge.target ?? edge.to)\n\t\t\t\tconst edgeId = edge.id || `edge-${index}`\n\n\t\t\t\tfor (const source of sources) {\n\t\t\t\t\tfor (const target of targets) {\n\t\t\t\t\t\t// The line id must not be the edge id: a split renders\n\t\t\t\t\t\t// one edge as several lines, and v-for keys collide.\n\t\t\t\t\t\tlines.push({\n\t\t\t\t\t\t\tid: `${edgeId}:${source}:${target}`,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\ttarget,\n\n\t\t\t\t\t\t\t// LET VUE FLOW ROUTE THE LINE.\n\t\t\t\t\t\t\t//\n\t\t\t\t\t\t\t// These carried no `type`, so every line fell back\n\t\t\t\t\t\t\t// to Vue Flow's default bezier — which crosses\n\t\t\t\t\t\t\t// nodes and doubles back on itself as soon as a\n\t\t\t\t\t\t\t// graph stops being a straight chain. That read as\n\t\t\t\t\t\t\t// \"our lines are disorderly\", and the instinct was\n\t\t\t\t\t\t\t// to lay the graph out ourselves to compensate.\n\t\t\t\t\t\t\t//\n\t\t\t\t\t\t\t// `smoothstep` is orthogonal routing with rounded\n\t\t\t\t\t\t\t// corners: it is what the hand-drawn canvas was\n\t\t\t\t\t\t\t// imitating, and the flow-builder's own dead `#edge`\n\t\t\t\t\t\t\t// slot described the goal as \"orthogonal routing\n\t\t\t\t\t\t\t// plus an explicit arrowhead\". Both are Vue Flow\n\t\t\t\t\t\t\t// options we had simply never set.\n\t\t\t\t\t\t\t//\n\t\t\t\t\t\t\t// PER EDGE, and the document wins. `edge.lineType`\n\t\t\t\t\t\t\t// is stored on the connection, so a single awkward\n\t\t\t\t\t\t\t// line can be switched to `step`, `straight` or\n\t\t\t\t\t\t\t// `default` without moving a node — the seam an\n\t\t\t\t\t\t\t// edge-level control hangs off.\n\t\t\t\t\t\t\t//\n\t\t\t\t\t\t\t// ⚠️ THE ROUTER TRAVELS IN `data`, NOT IN `type`.\n\t\t\t\t\t\t\t// It sat in `type` when the router was the only\n\t\t\t\t\t\t\t// thing an edge carried, and that quietly ruled out\n\t\t\t\t\t\t\t// everything else: Vue Flow reads `type` to choose\n\t\t\t\t\t\t\t// the COMPONENT that draws the line, so naming a\n\t\t\t\t\t\t\t// router there means the built-in edge answers and\n\t\t\t\t\t\t\t// no label, marker control or payload affordance\n\t\t\t\t\t\t\t// can ever be attached. `default` selects\n\t\t\t\t\t\t\t// CnFlowEdge, which reads the router back out of\n\t\t\t\t\t\t\t// `data`. Same distinction the node side already\n\t\t\t\t\t\t\t// records — `type` is a component, and a domain\n\t\t\t\t\t\t\t// value put there is a component that does not\n\t\t\t\t\t\t\t// exist.\n\t\t\t\t\t\t\ttype: 'default',\n\n\t\t\t\t\t\t\t// ⚠️ SIZED, BECAUSE THE DEFAULT ARROWHEAD WAS DRAWN\n\t\t\t\t\t\t\t// UNDERNEATH THE PORT HANDLE.\n\t\t\t\t\t\t\t//\n\t\t\t\t\t\t\t// `'arrowclosed'` on its own renders a 12.5px arrow\n\t\t\t\t\t\t\t// at the path's end — which is exactly where the\n\t\t\t\t\t\t\t// target node's handle sits, and that handle is an\n\t\t\t\t\t\t\t// 18px filled circle in a layer Vue Flow paints\n\t\t\t\t\t\t\t// ABOVE the edges. So the arrow was there the whole\n\t\t\t\t\t\t\t// time, measurably, and no user could see it: the\n\t\t\t\t\t\t\t// canvas read as a set of undirected lines.\n\t\t\t\t\t\t\t//\n\t\t\t\t\t\t\t// 22px is chosen against the handle, not for looks\n\t\t\t\t\t\t\t// — the arrow has to extend beyond it to read as an\n\t\t\t\t\t\t\t// arrow at all. Colour is deliberately NOT set here:\n\t\t\t\t\t\t\t// Vue Flow writes it as an inline style on the\n\t\t\t\t\t\t\t// polyline, so it is themed in CSS instead (see\n\t\t\t\t\t\t\t// `.vue-flow__arrowhead` in CnGraphCanvas) and\n\t\t\t\t\t\t\t// follows dark mode.\n\t\t\t\t\t\t\tmarkerEnd: edge.markerEnd || { type: 'arrowclosed', width: 22, height: 22 },\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\tlineType: edge.lineType || DEFAULT_EDGE_LINE_TYPE,\n\t\t\t\t\t\t\t\tlabelT: edge.labelT,\n\t\t\t\t\t\t\t\tlabel: edge.title || edge.label || '',\n\t\t\t\t\t\t\t\tedge,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn lines\n\t\t},\n\n\t\t/**\n\t\t * The nodes a run enters through, decided the way the engine decides.\n\t\t *\n\t\t * @return {Array<string>} Their ids.\n\t\t */\n\t\tstartNodeIds() {\n\t\t\tconst nodes = this.nodes\n\t\t\tconst explicit = nodes.filter((n) => n.start === true || n.initial === true).map((n) => n.id)\n\t\t\tif (explicit.length) {\n\t\t\t\treturn explicit\n\t\t\t}\n\n\t\t\tconst targeted = new Set(this.canvasEdges.map((line) => line.target))\n\t\t\tconst sources = nodes.filter((n) => !targeted.has(n.id)).map((n) => n.id)\n\t\t\tif (sources.length) {\n\t\t\t\treturn sources\n\t\t\t}\n\n\t\t\treturn nodes.length ? [nodes[0].id] : []\n\t\t},\n\n\t\t/**\n\t\t * What stops this flow from ever finishing, by node ROLE.\n\t\t *\n\t\t * An empty flow reports nothing — there is no point telling the author\n\t\t * a blank canvas is incomplete.\n\t\t *\n\t\t * @return {{trigger: boolean, end: boolean}} The missing roles.\n\t\t */\n\t\tmissingEnds() {\n\t\t\tif (!this.nodes.length) {\n\t\t\t\treturn { trigger: false, end: false }\n\t\t\t}\n\n\t\t\tconst roles = this.nodes.map((n) => this.roleOfNodeType(n.type))\n\n\t\t\treturn {\n\t\t\t\ttrigger: !roles.includes('trigger'),\n\t\t\t\tend: !roles.includes('end'),\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Whether the watched run is still going.\n\t\t *\n\t\t * Read from the run's own `status` against the engine's non-terminal\n\t\t * set, never from `watching` — the poll loop can be paused (hidden\n\t\t * tab) or already stopped (terminal status seen) while the last\n\t\t * fetched state is what the canvas should keep painting.\n\t\t *\n\t\t * @param {object} state The store state.\n\t\t * @return {boolean} True while the run's status is non-terminal.\n\t\t */\n\t\twatchedRunActive: (state) => FLOW_RUN_ACTIVE_STATUSES.includes(state.watchedRun?.status),\n\n\t\t/**\n\t\t * The steps the latest poll ADDED, in log order.\n\t\t *\n\t\t * Index-diffed against what was already exposed, so a consumer can\n\t\t * tell new steps from ones it has already animated. Exact because the\n\t\t * log only grows within a run — see `watchedSteps`.\n\t\t *\n\t\t * @param {object} state The store state.\n\t\t * @return {Array<object>} The engine's log entries, as delivered.\n\t\t */\n\t\tnewWatchedSteps: (state) => state.watchedSteps.slice(state.watchedNewFrom),\n\n\t\t/**\n\t\t * The flow as the engine would run it.\n\t\t *\n\t\t * @param {object} state The store state.\n\t\t * @return {object} The runnable document.\n\t\t */\n\t\tflowForRun: (state) => ({\n\t\t\t...state.flow,\n\t\t\tnodes: state.flow.nodes || [],\n\t\t\tedges: state.flow.edges || [],\n\t\t}),\n\t},\n\n\tactions: {\n\t\t/**\n\t\t * Declare that the editor is opening, before the first request goes out.\n\t\t *\n\t\t * 🔴 CALLED FROM `created()`, NOT FROM `load()`, AND THAT IS THE FIX.\n\t\t * A flag raised inside `load()` is raised one tick too late: Vue renders\n\t\t * the component before `mounted()` runs, so the first paint had\n\t\t * `bootstrapping === false` with nothing loaded, the exact frame that\n\t\t * showed the editor's toolbar over \"No steps yet\". The surface that is\n\t\t * about to load says so before it renders.\n\t\t *\n\t\t * @param {string|null} runUuid The run the URL named, if it named one.\n\t\t * @return {void}\n\t\t */\n\t\tbeginBootstrap(runUuid = null) {\n\t\t\tthis.bootstrapping = true\n\t\t\tthis.openingRunUuid = runUuid || null\n\t\t},\n\n\t\t/**\n\t\t * The arrival has settled: the flow, and the run if there was one, are\n\t\t * as loaded as they are going to get.\n\t\t *\n\t\t * Lowers both flags. A failed load lands here too, via a `finally` at\n\t\t * the call site, because a canvas stuck saying \"loading\" forever is a\n\t\t * worse lie than the one this replaced.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tendBootstrap() {\n\t\t\tthis.bootstrapping = false\n\t\t\tthis.openingRunUuid = null\n\t\t},\n\n\t\t/**\n\t\t * Enter run view for a run that has not been read yet.\n\t\t *\n\t\t * Separate from `beginBootstrap` because a run can also be opened on a\n\t\t * flow that is already on the canvas: `?run=` changing on the same route\n\t\t * reuses the component, so there is no fresh arrival to hang it on.\n\t\t *\n\t\t * @param {string} runUuid The run being opened.\n\t\t * @return {void}\n\t\t */\n\t\tbeginOpeningRun(runUuid) {\n\t\t\tif (!runUuid) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.openingRunUuid = runUuid\n\t\t},\n\n\t\t/**\n\t\t * The run has been read, or the attempt failed. Either way it is no\n\t\t * longer being opened, and `inspectedRunUuid` is what holds run view\n\t\t * from here on.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tendOpeningRun() {\n\t\t\tthis.openingRunUuid = null\n\t\t},\n\n\t\t/**\n\t\t * Load the flows this surface is scoped to, plus both catalogues.\n\t\t *\n\t\t * @param {object} options Load options.\n\t\t * @param {string|null} options.app Restrict to one owning app id.\n\t\t * @param {string|null} options.id The flow to open, or 'new'.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync load({ app = null, id = null } = {}) {\n\t\t\t// A BLANK flow is initialised BEFORE the network, and this ordering\n\t\t\t// is the fix for #607 rather than a tidy-up.\n\t\t\t//\n\t\t\t// `emptyFlow()` has `name: ''`, and only `open('new')` supplies the\n\t\t\t// default name. `open()` used to run at the tail of this method,\n\t\t\t// behind `await GET /api/flows` — a flow LIST that starting a blank\n\t\t\t// flow does not need. Meanwhile the sidebar is already rendered and\n\t\t\t// Save already enabled, because `nodeCatalog` was populated by the\n\t\t\t// index page's own `load()` and this store is a singleton that\n\t\t\t// survives the route change.\n\t\t\t//\n\t\t\t// So there was a window in which the editor invited a Save of a flow\n\t\t\t// with no name, which `FlowController::create()` answers 400 \"A flow\n\t\t\t// needs a name.\" — measured at 9 of 10 attempts against a fresh\n\t\t\t// instance. The same late `open('new')` also reset `this.flow`, so a\n\t\t\t// step placed during the window was wiped, and a save landing after\n\t\t\t// it stored `nodes: []`.\n\t\t\t//\n\t\t\t// Nothing about a blank flow depends on the server, so it is set up\n\t\t\t// first, and NOT re-opened at the tail — re-opening is what threw the\n\t\t\t// user's work away.\n\t\t\t//\n\t\t\t// `id === 'new'` ONLY, never `id === null`. `save()` calls this\n\t\t\t// method as `load({ app })` to refresh the list, and a null id has\n\t\t\t// always meant \"reload the list, leave the open flow alone\". Treating\n\t\t\t// that as blank would reset the flow immediately after storing it,\n\t\t\t// discarding the id the server had just returned.\n\t\t\tconst isBlank = (id === 'new')\n\t\t\tif (isBlank === true) {\n\t\t\t\tthis.open('new', app)\n\t\t\t}\n\n\t\t\tthis.loading = true\n\t\t\tthis.error = null\n\t\t\ttry {\n\t\t\t\tconst params = app ? { app } : {}\n\t\t\t\tconst response = await axios.get(generateUrl('/apps/openregister/api/flows'), { params })\n\t\t\t\tthis.flows = response.data?.results || []\n\t\t\t} catch (error) {\n\t\t\t\t// Surfaced, not swallowed: an empty list with no trace of why is\n\t\t\t\t// indistinguishable from \"this instance has no flows\".\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not load flows', error)\n\t\t\t\tthis.flows = []\n\t\t\t\tthis.error = error\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\n\t\t\t// Both catalogues are kept OFF the critical path: the canvas is\n\t\t\t// usable while they resolve, and a failure costs the palette and the\n\t\t\t// trigger list rather than the editor.\n\t\t\tthis.loadNodeCatalog()\n\t\t\tthis.loadEventCatalog()\n\n\t\t\t// A blank flow was already opened above, before the network. Opening\n\t\t\t// it again here is what used to wipe a step the user had placed in\n\t\t\t// the meantime, so only a STORED flow is opened at this point — it\n\t\t\t// genuinely needs `this.flows`, which the request above just filled.\n\t\t\tif (id !== null && isBlank === false) {\n\t\t\t\t// 🔴 THE LIST IS NOT THE ONLY PLACE A FLOW CAN LIVE.\n\t\t\t\t//\n\t\t\t\t// `open()` resolves a flow by looking it up in `this.flows`, and\n\t\t\t\t// that list was just fetched scoped to ONE app. A flow belonging\n\t\t\t\t// to a different app is therefore absent, `open()` finds no match,\n\t\t\t\t// and — before this — returned silently, leaving the canvas\n\t\t\t\t// painted with whatever was there before: blank.\n\t\t\t\t//\n\t\t\t\t// That is not a hypothetical. A dossiq case ran eighteen flow runs\n\t\t\t\t// of a flow whose `app` is `openregister`; clicking any of them\n\t\t\t\t// opened `/flows/<id>` on dossiq's flow page, which loads\n\t\t\t\t// `?app=dossiq`, and the editor came up empty with no error.\n\t\t\t\t// Cross-app runs are ordinary — a case is driven by flows from\n\t\t\t\t// whichever app authored them.\n\t\t\t\t//\n\t\t\t\t// `GET /api/flows/{id}` resolves by uuid with no app filter, so\n\t\t\t\t// one request answers it. Only reached on a miss, so the common\n\t\t\t\t// case costs nothing.\n\t\t\t\tawait this.ensureFlowLoaded(id)\n\t\t\t\tthis.open(id, app)\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Make sure a flow is present in `this.flows` before `open()` looks for it.\n\t\t *\n\t\t * Fetches the single flow by uuid when the app-scoped list did not carry\n\t\t * it. A 404 is left alone: `open()` reports the not-found state, which is\n\t\t * the honest answer and the one the canvas can render.\n\t\t *\n\t\t * @param {string} id The flow uuid.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync ensureFlowLoaded(id) {\n\t\t\tif (!id || id === 'new') {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (this.flows.some((flow) => String(flow.id) === String(id))) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst response = await axios.get(generateUrl('/apps/openregister/api/flows/' + encodeURIComponent(id)))\n\t\t\t\tconst flow = response.data\n\t\t\t\tif (flow && flow.id) {\n\t\t\t\t\tthis.flows = [...this.flows, flow]\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\t// Surfaced, not swallowed — but not fatal either. `open()` sets\n\t\t\t\t// the not-found state right after this, and that is what the\n\t\t\t\t// canvas renders; throwing here would take out the whole page for\n\t\t\t\t// a flow that simply is not there any more.\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not resolve flow by id', id, error)\n\t\t\t}\n\t\t},\n\n\t\tasync loadNodeCatalog() {\n\t\t\tthis.catalogLoading = true\n\t\t\ttry {\n\t\t\t\tconst response = await axios.get(generateUrl('/apps/openregister/api/flow/node-catalog'))\n\t\t\t\tthis.nodeCatalog = response.data?.results || []\n\t\t\t} catch (error) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not load the node catalogue', error)\n\t\t\t\tthis.nodeCatalog = []\n\t\t\t} finally {\n\t\t\t\tthis.catalogLoading = false\n\t\t\t}\n\t\t},\n\n\t\tasync loadEventCatalog() {\n\t\t\ttry {\n\t\t\t\tconst response = await axios.get(generateUrl('/apps/openregister/api/flow/event-catalog'))\n\t\t\t\tthis.eventCatalog = response.data?.results || []\n\t\t\t} catch (error) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not load the event catalogue', error)\n\t\t\t\tthis.eventCatalog = []\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Put the flow named by the route onto the canvas.\n\t\t *\n\t\t * @param {string} id The flow uuid, or 'new'.\n\t\t * @param {string|null} app The owning app for a new flow.\n\t\t * @return {void}\n\t\t */\n\t\topen(id, app = null) {\n\t\t\tthis.selectedNodeId = null\n\t\t\tthis.editingNodeId = null\n\t\t\t// Cleared with the rest of the per-flow state. A refusal left over\n\t\t\t// from the last flow would tell the author their NEW draft is\n\t\t\t// published and offer to draft it again.\n\t\t\tthis.lifecycleRefusal = null\n\t\t\tthis.versions = []\n\t\t\tthis.runs = []\n\t\t\tthis.steps = []\n\t\t\tthis.runObjects = []\n\t\t\tthis.inspectedRunUuid = null\n\t\t\tthis.runDetail = null\n\t\t\tthis.checkResult = null\n\n\t\t\t// A watch is per run and a run is per flow: polling the previous\n\t\t\t// flow's run from the next flow's editor would keep painting a run\n\t\t\t// this canvas cannot show.\n\t\t\tthis.stopWatching()\n\t\t\tthis.watchedRunUuid = null\n\t\t\tthis.watchedRun = null\n\t\t\tthis.watchedSteps = []\n\t\t\tthis.watchedNewFrom = 0\n\t\t\tthis.replayUuid = null\n\n\t\t\t// Cleared on every open, so a not-found id from the previous route\n\t\t\t// cannot keep a resolvable flow behind an error screen.\n\t\t\tthis.notFound = null\n\n\t\t\t// Cleared with the rest of the per-flow state. A snapshot left over\n\t\t\t// from the previous flow's run would keep THIS flow's canvas locked,\n\t\t\t// and `liveGraph` would hold another flow's nodes ready to be\n\t\t\t// restored over it.\n\t\t\tthis.viewingVersion = null\n\t\t\tthis.liveGraph = null\n\t\t\tthis.runGraphNotice = null\n\n\t\t\tif (!id || id === 'new') {\n\t\t\t\t// A new flow is runnable on demand until its author picks a real\n\t\t\t\t// trigger, so the flow-level trigger and the seeded start node\n\t\t\t\t// say the same thing.\n\t\t\t\tthis.flow = { ...emptyFlow(), name: t('nextcloud-vue', 'New flow'), app: app || 'openregister', trigger: 'manual' }\n\t\t\t\tthis.seedStartNode()\n\t\t\t\tthis.dirty = false\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst match = this.flows.find((flow) => String(flow.id) === String(id))\n\t\t\tif (!match) {\n\t\t\t\t// A blank canvas and no explanation is the worst of the three\n\t\t\t\t// possible answers here. `notFound` lets the host say which id it\n\t\t\t\t// could not resolve, so \"this flow was deleted\" and \"this page is\n\t\t\t\t// broken\" stop looking identical.\n\t\t\t\tthis.notFound = String(id)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.flow = {\n\t\t\t\t...emptyFlow(),\n\t\t\t\t...match,\n\t\t\t\t// Deep-copied so an edit on the canvas does not mutate the list\n\t\t\t\t// row behind it — otherwise cancelling an edit leaves the list\n\t\t\t\t// showing changes that were never saved.\n\t\t\t\tnodes: Array.isArray(match.nodes) ? JSON.parse(JSON.stringify(match.nodes)) : [],\n\t\t\t\tedges: Array.isArray(match.edges) ? JSON.parse(JSON.stringify(match.edges)) : [],\n\t\t\t}\n\t\t\tthis.dirty = false\n\n\t\t\t// A flow nobody has ever laid out opens as a PILE, not as a graph.\n\t\t\t//\n\t\t\t// Generated and imported flows carry no coordinates at all — a\n\t\t\t// 76-node flow measured on a live instance had 73 nodes with no\n\t\t\t// position — and every one of those lands on the same point. The\n\t\t\t// result is indistinguishable from an empty canvas: one node's\n\t\t\t// worth of pixels, with the rest underneath it.\n\t\t\t//\n\t\t\t// ⚠️ NOT `autoSort()`. This fallback used to call it, and autoSort\n\t\t\t// gates on `pushUndo()`, which refuses when the graph is locked —\n\t\t\t// and a flow imported from `x-openregister-flows` is PUBLISHED the\n\t\t\t// moment it exists (SchemaFlowImportListener publishes on import).\n\t\t\t// So the exact flows that always need this fallback were the ones\n\t\t\t// it silently skipped: dossiq's 18-node imported flow opened as a\n\t\t\t// pile, with the run replay's badges painting an unreadable point.\n\t\t\t// `applyRenderLayout()` computes coordinates without asking to\n\t\t\t// edit, which a rendering fallback never does.\n\t\t\tthis.applyRenderLayout()\n\n\t\t\tthis.loadRuns(id)\n\t\t},\n\n\t\t/**\n\t\t * Put the one node every flow starts from onto a blank canvas.\n\t\t *\n\t\t * A new flow renders the SAME editor as an existing one, holding only a\n\t\t * starting point — never an empty page that looks like a different\n\t\t * surface. The id is hard-coded rather than read from the catalogue\n\t\t * because the catalogue loads after `open('new')` returns; if an\n\t\t * instance's engine really does not know it, the card wears the\n\t\t * existing \"Unknown step\" warning instead of failing silently.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tseedStartNode() {\n\t\t\tthis.flow.nodes = [{\n\t\t\t\tid: `start-${Date.now().toString(36)}`,\n\t\t\t\ttype: 'openregister.trigger-manual',\n\t\t\t\tx: 80,\n\t\t\t\ty: 60,\n\t\t\t\tconfig: {},\n\t\t\t\tstart: true,\n\t\t\t}]\n\t\t},\n\n\t\t/**\n\t\t * Add a node of `type`, at an explicit canvas point when dropped.\n\t\t *\n\t\t * `type` is the catalogue id verbatim. Default placement stacks a\n\t\t * vertical chain near the left, with a gap about a card high so the\n\t\t * arrowhead and the result badge on the connecting edge both have room.\n\t\t *\n\t\t * @param {string} type The catalogue node id.\n\t\t * @param {number} x Canvas x (optional).\n\t\t * @param {number} y Canvas y (optional).\n\t\t * @return {void}\n\t\t */\n\t\t/**\n\t\t * Remember the current flow so the next edit can be undone.\n\t\t *\n\t\t * Called at the TOP of every mutating action, before the mutation — an\n\t\t * undo stack that records the state AFTER a change can only ever return\n\t\t * you to where you already are.\n\t\t *\n\t\t * Deep-cloned, not referenced. `flow` is mutated in place by several\n\t\t * actions, so a stored reference would be rewritten by the very edit it\n\t\t * exists to reverse and every entry would collapse to \"now\".\n\t\t *\n\t\t * Capped: each entry holds a whole flow document, and a canvas gets a\n\t\t * lot of small edits. 50 is far past what anyone reaches for and still\n\t\t * bounded.\n\t\t *\n\t\t * 🔴 IT ALSO ANSWERS WHETHER THE EDIT MAY HAPPEN AT ALL. Every graph\n\t\t * mutation snapshots here first, which makes this the one place the\n\t\t * published-is-immutable rule can be applied without nine call sites\n\t\t * each remembering to. A locked flow gets `false` and the caller\n\t\t * returns before touching the document — the alternative, letting the\n\t\t * canvas edit freely and discovering the refusal on save, loses the\n\t\t * author's work at the worst possible moment.\n\t\t *\n\t\t * @return {boolean} Whether the caller may proceed with its edit.\n\t\t */\n\t\tpushUndo() {\n\t\t\tif (this.graphLocked) {\n\t\t\t\tthis.lifecycleRefusal = {\n\t\t\t\t\treason: 'version-immutable',\n\t\t\t\t\tlifecycleStatus: this.lifecycleStatus,\n\t\t\t\t}\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\t// The edit is going ahead, so whatever the flow's state last refused\n\t\t\t// is no longer the situation. A refusal that outlives its cause is\n\t\t\t// a message the author learns to ignore, and then ignores the true\n\t\t\t// one too. Cleared HERE for the same reason the lock is checked\n\t\t\t// here: it is the one place every graph mutation passes through.\n\t\t\tthis.lifecycleRefusal = null\n\n\t\t\tthis.snapshot()\n\n\t\t\treturn true\n\t\t},\n\n\t\t/**\n\t\t * Push one undo entry, and keep the stack capped.\n\t\t *\n\t\t * 🔴 THE ONLY PLACE THAT PUSHES. Metadata edits are exempt from the\n\t\t * published-is-immutable lock but still want undo, and the first version\n\t\t * of that exemption pushed to `undoStack` directly — bypassing the trim\n\t\t * and letting the stack grow past its cap (caught at 60/50 by\n\t\t * `useFlowStoreUndo.spec.js`). A cap enforced in two places is a cap\n\t\t * enforced in one of them.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tsnapshot() {\n\t\t\tthis.undoStack.push(JSON.stringify(this.flow))\n\t\t\tif (this.undoStack.length > 50) {\n\t\t\t\tthis.undoStack.shift()\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Step back one edit.\n\t\t *\n\t\t * Entries that match the current state are DISCARDED rather than\n\t\t * applied. Actions snapshot before they know whether they will change\n\t\t * anything — `connect()` refuses a duplicate, `setNodeConfig()` may be\n\t\t * handed the value already stored — so without this a user could press\n\t\t * Ctrl+Z and watch nothing happen, which reads as \"undo is broken\"\n\t\t * rather than \"that edit was a no-op\".\n\t\t *\n\t\t * @return {boolean} Whether anything was undone.\n\t\t */\n\t\tundo() {\n\t\t\tconst current = JSON.stringify(this.flow)\n\n\t\t\twhile (this.undoStack.length > 0) {\n\t\t\t\tconst previous = this.undoStack.pop()\n\t\t\t\tif (previous === current) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tthis.flow = JSON.parse(previous)\n\t\t\t\tthis.dirty = true\n\n\t\t\t\t// The verdict described the graph that was just replaced.\n\t\t\t\tthis.checkResult = null\n\n\t\t\t\t// A node that no longer exists cannot stay selected, and an open\n\t\t\t\t// editor for it would render against nothing.\n\t\t\t\tif (this.nodes.some((node) => node.id === this.selectedNodeId) === false) {\n\t\t\t\t\tthis.selectedNodeId = null\n\t\t\t\t}\n\t\t\t\tif (this.nodes.some((node) => node.id === this.editingNodeId) === false) {\n\t\t\t\t\tthis.editingNodeId = null\n\t\t\t\t}\n\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\treturn false\n\t\t},\n\n\t\taddNode(type, x = null, y = null) {\n\t\t\tif (!this.pushUndo()) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst index = this.nodes.length\n\t\t\tconst node = {\n\t\t\t\tid: `${type}-${Date.now().toString(36)}-${index}`,\n\t\t\t\ttype,\n\t\t\t\tx: x === null ? 80 : x,\n\t\t\t\ty: y === null ? (60 + index * 170) : y,\n\t\t\t\tconfig: {},\n\t\t\t}\n\t\t\tif (index === 0) {\n\t\t\t\tnode.start = true\n\t\t\t}\n\n\t\t\tthis.flow.nodes = [...this.nodes, node]\n\t\t\tthis.selectedNodeId = node.id\n\t\t\tthis.dirty = true\n\t\t\tthis.checkResult = null\n\t\t},\n\n\t\t/**\n\t\t * WRITES BOTH SPELLINGS, FOR THE SAME REASON connect() WRITES `from`/`to`.\n\t\t *\n\t\t * `position: {x, y}` is the shape the SERVER stores — measured on a live\n\t\t * instance, not one of 100 persisted flows carried a flat `x`/`y` node.\n\t\t * Writing only flat coordinates therefore meant a dragged node's new\n\t\t * position never survived the save: it round-tripped back as no position\n\t\t * at all, and the node reloaded at the origin.\n\t\t *\n\t\t * Flat `x`/`y` is kept alongside it because autoSort() and addNode()\n\t\t * speak that spelling in memory, and dropping it here would make a moved\n\t\t * node inconsistent with an unmoved one within the same session.\n\t\t *\n\t\t * @param {object} move The move.\n\t\t * @param {string} move.id The node that moved.\n\t\t * @param {number} move.x Its new x, in canvas units.\n\t\t * @param {number} move.y Its new y.\n\t\t * @return {void}\n\t\t */\n\t\t/**\n\t\t * Duplicate a step, offset so the copy is visibly its own node.\n\t\t *\n\t\t * The config is deep-cloned. A shallow copy would leave both steps\n\t\t * sharing one config object, so editing the duplicate would silently\n\t\t * rewrite the original — the copy would look independent and not be.\n\t\t *\n\t\t * Edges are deliberately NOT copied. A duplicate wired exactly like its\n\t\t * original would fan the flow in two at that point, which is a different\n\t\t * graph from the one the author asked for; they connect the copy where\n\t\t * they want it.\n\t\t *\n\t\t * `start` is not copied either: a flow has one starting point, and a\n\t\t * second node claiming it makes the entry ambiguous.\n\t\t *\n\t\t * @param {string} id The node to copy.\n\t\t * @return {string|null} The new node's id, or null when there was nothing to copy.\n\t\t */\n\t\tcopyNode(id) {\n\t\t\tconst source = this.nodes.find((node) => node.id === id)\n\t\t\tif (source === undefined) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\t// `null`, matching the not-found case above: this method's contract\n\t\t\t// is \"the new node's id, or null when nothing was copied\", and a\n\t\t\t// bare `return` would hand callers `undefined` for one refusal and\n\t\t\t// `null` for the other.\n\t\t\tif (!this.pushUndo()) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\tconst copy = {\n\t\t\t\t...source,\n\t\t\t\tid: `${source.type}-${Date.now().toString(36)}-${this.nodes.length}`,\n\t\t\t\tx: (source.x ?? 0) + 40,\n\t\t\t\ty: (source.y ?? 0) + 40,\n\t\t\t\tconfig: JSON.parse(JSON.stringify(source.config ?? {})),\n\t\t\t}\n\t\t\tcopy.position = { x: copy.x, y: copy.y }\n\t\t\tdelete copy.start\n\t\t\tdelete copy.initial\n\n\t\t\tthis.flow.nodes = [...this.nodes, copy]\n\t\t\tthis.selectedNodeId = copy.id\n\t\t\tthis.dirty = true\n\t\t\tthis.checkResult = null\n\n\t\t\treturn copy.id\n\t\t},\n\n\t\tmoveNode({ id, x, y }) {\n\t\t\tif (!this.pushUndo()) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.flow.nodes = this.nodes.map((node) => (node.id === id ? { ...node, x, y, position: { x, y } } : node))\n\t\t\tthis.dirty = true\n\t\t},\n\n\t\t/**\n\t\t * Connect two nodes (no duplicates, no self-edges).\n\t\t *\n\t\t * WRITES `from`/`to`, WHICH IS THE DIALECT THE ENGINE READS.\n\t\t *\n\t\t * This used to store `{source, target}`. The canvas rendered it — the\n\t\t * `canvasEdges` getter accepts either spelling — so the author saw the\n\t\t * connection, and the save succeeded. But OpenRegister's flow engine\n\t\t * only understands `from`/`to`, so every edge drawn in the editor was\n\t\t * INVISIBLE to it: the saved flow validated with a `node-dead-end`\n\t\t * warning and a run was refused outright with \"node … has no outgoing\n\t\t * edge and does not end the flow\".\n\t\t *\n\t\t * The editor could therefore not produce a runnable multi-node flow at\n\t\t * all, while looking like it had. Measured against a live instance:\n\t\t * `edges: [{source, target}]` returns that warning, `[{from, to}]`\n\t\t * returns clean.\n\t\t *\n\t\t * The duplicate check reads BOTH spellings, so a flow loaded from the\n\t\t * server (which is `from`/`to`) is not re-connected into a duplicate.\n\t\t *\n\t\t * @param {object} payload The connection.\n\t\t * @param {string} payload.source Source node id.\n\t\t * @param {string} payload.target Target node id.\n\t\t * @return {void}\n\t\t */\n\t\tconnect({ source, target }) {\n\t\t\tif (!this.pushUndo()) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (!source || !target || source === target) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst exists = this.edges.some((edge) => (edge.source ?? edge.from) === source && (edge.target ?? edge.to) === target)\n\t\t\tif (exists) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.flow.edges = [...this.edges, { from: source, to: target }]\n\t\t\tthis.dirty = true\n\t\t\tthis.checkResult = null\n\t\t},\n\n\t\t/**\n\t\t * The stored edge a drawn line came from, and how it is stored.\n\t\t *\n\t\t * Both dialects and both cardinalities: an edge may speak\n\t\t * `{source, target}` or `{from, to}`, and either endpoint may be a LIST\n\t\t * (several `from` is a join, several `to` is a split). So \"the edge for\n\t\t * line a→c\" is not simply `edges.find(...)` — it may be one entry among\n\t\t * three that the same record draws.\n\t\t *\n\t\t * @param {object} line The line.\n\t\t * @param {string} line.source Its source node id.\n\t\t * @param {string} line.target Its target node id.\n\t\t * @return {{index: number, edge: object, sourceKey: string, targetKey: string, sources: Array<string>, targets: Array<string>}|null}\n\t\t * Where it lives, or null when no stored edge draws it.\n\t\t */\n\t\tlocateEdge({ source, target }) {\n\t\t\tconst toList = (value) => {\n\t\t\t\tif (Array.isArray(value)) {\n\t\t\t\t\treturn value.filter((v) => v !== null && v !== undefined && v !== '')\n\t\t\t\t}\n\n\t\t\t\treturn (value === null || value === undefined || value === '') ? [] : [value]\n\t\t\t}\n\n\t\t\tconst edges = this.edges\n\t\t\tfor (let index = 0; index < edges.length; index++) {\n\t\t\t\tconst edge = edges[index]\n\t\t\t\tconst sourceKey = edge.source !== undefined ? 'source' : 'from'\n\t\t\t\tconst targetKey = edge.target !== undefined ? 'target' : 'to'\n\t\t\t\tconst sources = toList(edge[sourceKey])\n\t\t\t\tconst targets = toList(edge[targetKey])\n\n\t\t\t\tif (sources.includes(source) && targets.includes(target)) {\n\t\t\t\t\treturn { index, edge, sourceKey, targetKey, sources, targets }\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn null\n\t\t},\n\n\t\t/**\n\t\t * Remove ONE drawn connection.\n\t\t *\n\t\t * ⚠️ ONE LINE, NOT ONE RECORD. Deleting a→c out of `{from: 'a', to:\n\t\t * ['b','c']}` must leave a→b standing: dropping the whole record because\n\t\t * it happens to be where a→c is stored would silently delete a second\n\t\t * connection the author never selected. So a multi-line record is\n\t\t * narrowed rather than removed, and only a record left with nothing on\n\t\t * one end goes.\n\t\t *\n\t\t * @param {object} line The line to remove.\n\t\t * @param {string} line.source Its source node id.\n\t\t * @param {string} line.target Its target node id.\n\t\t * @return {void}\n\t\t */\n\t\tremoveEdge({ source, target }) {\n\t\t\tconst found = this.locateEdge({ source, target })\n\t\t\tif (found === null) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (!this.pushUndo()) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst targets = found.targets.filter((id) => id !== target)\n\t\t\tconst sources = found.sources.length > 1 ? found.sources.filter((id) => id !== source) : found.sources\n\n\t\t\tconst edges = [...this.edges]\n\t\t\tif (targets.length === 0 || sources.length === 0) {\n\t\t\t\tedges.splice(found.index, 1)\n\t\t\t} else {\n\t\t\t\tedges[found.index] = {\n\t\t\t\t\t...found.edge,\n\t\t\t\t\t[found.sourceKey]: sources.length === 1 ? sources[0] : sources,\n\t\t\t\t\t[found.targetKey]: targets.length === 1 ? targets[0] : targets,\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.flow.edges = edges\n\t\t\tthis.dirty = true\n\t\t\tthis.checkResult = null\n\t\t},\n\n\t\t/**\n\t\t * Set a field — `title`, `lineType` — on ONE drawn connection.\n\t\t *\n\t\t * ⚠️ SPLITS A MULTI-LINE RECORD FIRST. Writing `lineType` straight onto\n\t\t * `{from: 'a', to: ['b','c']}` would restyle both lines from a control\n\t\t * the author opened on one of them. A per-line control whose blast\n\t\t * radius is three lines is not a per-line control, so the line being\n\t\t * edited is lifted into a record of its own and the field is set there.\n\t\t *\n\t\t * Takes a whole set of fields rather than one, so pasting a copied\n\t\t * presentation is a SINGLE undo step. Two `key`/`value` calls in a row\n\t\t * would leave a user pressing Ctrl+Z twice to reverse one paste, and the\n\t\t * first press would land on a half-pasted line.\n\t\t *\n\t\t * @param {object} change The change.\n\t\t * @param {string} change.source The line's source node id.\n\t\t * @param {string} change.target The line's target node id.\n\t\t * @param {object} change.fields The fields to set, as a plain object.\n\t\t * @return {void}\n\t\t */\n\t\tsetEdgeFields({ source, target, fields }) {\n\t\t\tconst found = this.locateEdge({ source, target })\n\t\t\tif (found === null) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (!this.pushUndo()) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst edges = [...this.edges]\n\t\t\tconst drawsOneLine = found.sources.length === 1 && found.targets.length === 1\n\n\t\t\tif (drawsOneLine) {\n\t\t\t\tedges[found.index] = { ...found.edge, ...fields }\n\t\t\t} else {\n\t\t\t\t// Narrow the record to the lines this one is NOT, then append the\n\t\t\t\t// edited line as its own record.\n\t\t\t\tconst remainingTargets = found.targets.filter((id) => id !== target)\n\t\t\t\tedges[found.index] = {\n\t\t\t\t\t...found.edge,\n\t\t\t\t\t[found.targetKey]: remainingTargets.length === 1 ? remainingTargets[0] : remainingTargets,\n\t\t\t\t}\n\t\t\t\tedges.push({\n\t\t\t\t\t...found.edge,\n\t\t\t\t\tid: undefined,\n\t\t\t\t\t[found.sourceKey]: source,\n\t\t\t\t\t[found.targetKey]: target,\n\t\t\t\t\t...fields,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tthis.flow.edges = edges\n\t\t\tthis.dirty = true\n\t\t\tthis.checkResult = null\n\t\t},\n\n\t\t/**\n\t\t * Copy a connection's presentation, for pasting onto another.\n\t\t *\n\t\t * @param {object} line The line to copy from.\n\t\t * @param {string} line.source Its source node id.\n\t\t * @param {string} line.target Its target node id.\n\t\t * @return {void}\n\t\t */\n\t\tcopyEdgeStyle({ source, target }) {\n\t\t\tconst found = this.locateEdge({ source, target })\n\t\t\tif (found === null) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.edgeStyleClipboard = {\n\t\t\t\ttitle: found.edge.title ?? found.edge.label ?? '',\n\t\t\t\tlineType: found.edge.lineType || DEFAULT_EDGE_LINE_TYPE,\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Apply the copied presentation to another connection.\n\t\t *\n\t\t * @param {object} line The line to paste onto.\n\t\t * @param {string} line.source Its source node id.\n\t\t * @param {string} line.target Its target node id.\n\t\t * @return {void}\n\t\t */\n\t\tpasteEdgeStyle({ source, target }) {\n\t\t\tconst copied = this.edgeStyleClipboard\n\t\t\tif (copied === null) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.setEdgeFields({ source, target, fields: { lineType: copied.lineType, title: copied.title } })\n\t\t},\n\n\t\tremoveNode(id) {\n\t\t\tif (!this.pushUndo()) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.flow.nodes = this.nodes.filter((node) => node.id !== id)\n\t\t\t// BOTH spellings, or removing a node leaves its `from`/`to` edges\n\t\t\t// behind pointing at a node that no longer exists — and `from`/`to`\n\t\t\t// is exactly what the server stores, so every edge on a loaded flow\n\t\t\t// survived the deletion of the node it referenced.\n\t\t\tthis.flow.edges = this.edges.filter((edge) => (edge.source ?? edge.from) !== id && (edge.target ?? edge.to) !== id)\n\t\t\tthis.selectedNodeId = null\n\t\t\t// A dialog open on a line that ran through this node now describes\n\t\t\t// a connection the document no longer holds; every edge action would\n\t\t\t// find nothing and quietly do nothing.\n\t\t\tif (this.editingEdge?.source === id || this.editingEdge?.target === id) {\n\t\t\t\tthis.editingEdge = null\n\t\t\t}\n\t\t\tthis.dirty = true\n\t\t\tthis.checkResult = null\n\t\t},\n\n\t\t/**\n\t\t * Replace the selected node's whole config.\n\t\t *\n\t\t * The raw-config editor needs this: it edits the object as a document, so\n\t\t * a per-key setter could never REMOVE a key, and a node type whose keys\n\t\t * the builder does not know would accumulate stale ones.\n\t\t *\n\t\t * @param {object} config The new config object.\n\t\t * @return {void}\n\t\t */\n\t\tsetNodeConfigAll(config) {\n\t\t\tif (!this.pushUndo()) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (this.selectedNodeId === null) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.flow.nodes = this.nodes.map((node) => (\n\t\t\t\tnode.id === this.selectedNodeId ? { ...node, config: { ...config } } : node\n\t\t\t))\n\t\t\tthis.dirty = true\n\t\t\tthis.checkResult = null\n\t\t},\n\n\t\tsetNodeConfig(key, value) {\n\t\t\tif (!this.pushUndo()) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (this.selectedNodeId === null) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.flow.nodes = this.nodes.map((node) => (\n\t\t\t\tnode.id === this.selectedNodeId\n\t\t\t\t\t? { ...node, config: { ...(node.config || {}), [key]: value } }\n\t\t\t\t\t: node\n\t\t\t))\n\t\t\tthis.dirty = true\n\t\t\tthis.checkResult = null\n\t\t},\n\n\t\tsetFlowField(key, value) {\n\t\t\t// 🔴 THE LOCK APPLIES TO THE FOUR GRAPH KEYS AND NO OTHERS, exactly\n\t\t\t// where the server draws the line. `executionMode` and `limits` are\n\t\t\t// part of the pinned definition; `name`, `description` and `enabled`\n\t\t\t// are not — renaming a live process or switching it off are not\n\t\t\t// changes to the process. Locking those too would refuse edits the\n\t\t\t// API accepts and leave a published flow unmanageable.\n\t\t\tif (GRAPH_FIELDS.includes(key)) {\n\t\t\t\tif (!this.pushUndo()) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.snapshot()\n\t\t\t}\n\n\t\t\tthis.flow = { ...this.flow, [key]: value }\n\t\t\tthis.dirty = true\n\t\t},\n\n\t\t/**\n\t\t * Rename one node. The name is display only — the card's headline —\n\t\t * so it does not invalidate a check verdict.\n\t\t *\n\t\t * @param {string} id The node id.\n\t\t * @param {string} name The new name; empty falls back to the type label.\n\t\t * @return {void}\n\t\t */\n\t\tsetNodeName(id, name) {\n\t\t\tif (!this.pushUndo()) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.flow.nodes = this.nodes.map((node) => (\n\t\t\t\tnode.id === id ? { ...node, name } : node\n\t\t\t))\n\t\t\tthis.dirty = true\n\t\t},\n\n\t\t/**\n\t\t * Replace one node's whole config, by id.\n\t\t *\n\t\t * The edit dialog needs this: it commits a DRAFT on Done, for whichever\n\t\t * node it was opened on — which is not necessarily the selected one.\n\t\t *\n\t\t * @param {string} id The node id.\n\t\t * @param {object} config The new config object.\n\t\t * @return {void}\n\t\t */\n\t\tsetNodeConfigById(id, config) {\n\t\t\tif (!this.pushUndo()) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.flow.nodes = this.nodes.map((node) => (\n\t\t\t\tnode.id === id ? { ...node, config: { ...config } } : node\n\t\t\t))\n\t\t\tthis.dirty = true\n\t\t\tthis.checkResult = null\n\t\t},\n\n\t\t/**\n\t\t * Whether a node carries a position of its own.\n\t\t *\n\t\t * BOTH SPELLINGS, because both are in circulation: the server stores\n\t\t * `position: {x, y}` and the editor writes flat `x`/`y` in memory.\n\t\t * Checking only one would read a positioned flow as unpositioned and\n\t\t * rearrange it — the opposite of what load() wants.\n\t\t *\n\t\t * A node AT the origin counts as positioned. (0, 0) is a legitimate\n\t\t * place to put something, and treating it as \"no position\" would keep\n\t\t * relaying out a flow whose author had parked a node there.\n\t\t *\n\t\t * @param {object} node The node.\n\t\t * @return {boolean} True when the node says where it goes.\n\t\t */\n\t\thasPosition(node) {\n\t\t\treturn Number.isFinite(Number(node?.x))\n\t\t\t\t|| Number.isFinite(Number(node?.position?.x))\n\t\t},\n\n\t\t/**\n\t\t * Lay the nodes out left-to-right by how the flow actually runs.\n\t\t *\n\t\t * The pass lives in `flowGraphLayout.js`: longest-path layering seeded\n\t\t * from the start nodes with back edges dropped (a loop terminates the\n\t\t * layering instead of stretching it), one barycenter ordering pass per\n\t\t * column so parallel branches stay apart, fixed grid spacing.\n\t\t * Unreachable nodes go one column past everything — never at the\n\t\t * origin, where they would hide under the entry points. Coordinates\n\t\t * and NOTHING else change, which is what makes this safe to press on\n\t\t * a working flow.\n\t\t *\n\t\t * This is the EDIT — the toolbar button. It asks `pushUndo()` first,\n\t\t * so a locked graph refuses it, and it marks the document dirty so the\n\t\t * new layout is offered for saving. The rendering fallback that may\n\t\t * not do either of those things is `applyRenderLayout()`.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tautoSort() {\n\t\t\tif (!this.pushUndo()) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (!this.nodes.length) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.flow.nodes = layoutFlowNodes(this.nodes, this.canvasEdges, this.startNodeIds, { direction: this.layoutDirection })\n\t\t\tthis.dirty = true\n\t\t},\n\n\t\t/**\n\t\t * Give every node a usable position, without editing anything.\n\t\t *\n\t\t * A rendering fallback, not an edit: no undo entry, no dirty flag, no\n\t\t * lifecycle refusal — which is what lets it run on a PUBLISHED flow,\n\t\t * where `autoSort()` correctly refuses. The definition is untouched as\n\t\t * far as anyone else can tell: the coordinates live on the in-memory\n\t\t * copy `open()` already deep-cloned, nothing here persists them, and a\n\t\t * viewer who only looks never writes them anywhere. On a DRAFT the\n\t\t * author goes on to edit, the next save carries them along the\n\t\t * existing save path — which is the point: a once-opened flow becomes\n\t\t * stable instead of being relaid on every visit.\n\t\t *\n\t\t * Two cases, decided by the positions actually present:\n\t\t *\n\t\t * - No usable positions at all — none, or every positioned node piled\n\t\t * on one identical point — lays the WHOLE graph out fresh.\n\t\t * - An arranged graph with some position-less nodes keeps every placed\n\t\t * node exactly where its author put it and slots only the loose ones\n\t\t * beneath, in run order.\n\t\t *\n\t\t * @return {boolean} Whether any node was given a position.\n\t\t */\n\t\tapplyRenderLayout() {\n\t\t\tconst nodes = this.flow.nodes || []\n\t\t\tif (!nodes.length) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\tif (needsFullLayout(nodes)) {\n\t\t\t\tthis.flow.nodes = layoutFlowNodes(nodes, this.canvasEdges, this.startNodeIds, { direction: this.layoutDirection })\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\tif (nodes.some((node) => !this.hasPosition(node))) {\n\t\t\t\tthis.flow.nodes = placeLooseNodes(nodes, this.canvasEdges, this.startNodeIds, { direction: this.layoutDirection })\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\treturn false\n\t\t},\n\n\t\t/**\n\t\t * Ask the engine whether the CANVAS is runnable, without saving it.\n\t\t *\n\t\t * `POST /api/flow/validate` preflights the document against the live\n\t\t * node registry — the same check a save performs, minus the write. A\n\t\t * refusal (400) still carries the preflight's own report, so it is kept\n\t\t * as the result rather than treated as a transport failure: \"this flow\n\t\t * is not runnable, and here is why\" is the answer the button asked for.\n\t\t *\n\t\t * @return {Promise<object|null>} `{valid, blocking, warnings, message?}`, or null.\n\t\t */\n\t\tasync check() {\n\t\t\tthis.checking = true\n\t\t\tthis.error = null\n\t\t\ttry {\n\t\t\t\tconst response = await axios.post(\n\t\t\t\t\tgenerateUrl('/apps/openregister/api/flow/validate'),\n\t\t\t\t\t{ flow: this.flowForRun },\n\t\t\t\t)\n\t\t\t\tthis.checkResult = response.data || null\n\t\t\t\treturn this.checkResult\n\t\t\t} catch (error) {\n\t\t\t\tconst report = error?.response?.data\n\t\t\t\tif (report && typeof report === 'object' && 'valid' in report) {\n\t\t\t\t\tthis.checkResult = report\n\t\t\t\t\treturn this.checkResult\n\t\t\t\t}\n\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not check the flow', error)\n\t\t\t\tthis.error = error\n\t\t\t\treturn null\n\t\t\t} finally {\n\t\t\t\tthis.checking = false\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Create or update the flow.\n\t\t *\n\t\t * `owner` and `organisation` are never sent: the server stamps them, and\n\t\t * a client-supplied owner would let an author mint a flow that RUNS as\n\t\t * somebody else.\n\t\t *\n\t\t * 🔴 A VERSION SNAPSHOT IS NEVER SAVED, AND THE UI IS NOT THE GUARD.\n\t\t *\n\t\t * While `viewingVersion` is set the canvas holds a HISTORIC graph and\n\t\t * `flow.id` still names the live flow, so the PUT below would overwrite\n\t\t * the current flow with an old graph. The disabled Save button is not\n\t\t * protection: this method is also reached by the keyboard shortcut, and\n\t\t * the server only refuses a PUBLISHED flow — a flow that was published,\n\t\t * run, and then drafted again has version rows to inspect AND accepts\n\t\t * writes, which is exactly the combination that loses the graph.\n\t\t *\n\t\t * Returning null rather than throwing: nothing has gone wrong, the save\n\t\t * simply does not apply to what is on screen.\n\t\t *\n\t\t * @return {Promise<object|null>} The stored flow, or null on failure.\n\t\t */\n\t\tasync save() {\n\t\t\tif (this.viewingVersion !== null) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\tthis.saving = true\n\t\t\tthis.error = null\n\t\t\ttry {\n\t\t\t\tconst payload = { ...this.flow }\n\t\t\t\tdelete payload.owner\n\t\t\t\tdelete payload.organisation\n\n\t\t\t\tconst isNew = !payload.id\n\t\t\t\tconst response = isNew\n\t\t\t\t\t? await axios.post(generateUrl('/apps/openregister/api/flows'), payload)\n\t\t\t\t\t: await axios.put(generateUrl(`/apps/openregister/api/flows/${payload.id}`), payload)\n\n\t\t\t\tconst saved = response.data || null\n\t\t\t\tif (saved?.id) {\n\t\t\t\t\tthis.flow = { ...this.flow, id: saved.id }\n\t\t\t\t}\n\n\t\t\t\tawait this.load({ app: this.flow.app })\n\t\t\t\tthis.dirty = false\n\t\t\t\treturn saved\n\t\t\t} catch (error) {\n\t\t\t\t// A 409 is not a failure to save; it is the flow's STATE saying\n\t\t\t\t// this edit needs a draft first. Kept as the server's fields so\n\t\t\t\t// the sidebar can offer \"create a draft version\" rather than a\n\t\t\t\t// generic error nobody can act on.\n\t\t\t\tif (error?.response?.status === 409) {\n\t\t\t\t\tthis.lifecycleRefusal = {\n\t\t\t\t\t\treason: error.response.data?.reason || 'version-immutable',\n\t\t\t\t\t\tlifecycleStatus: error.response.data?.lifecycleStatus || null,\n\t\t\t\t\t}\n\t\t\t\t\treturn null\n\t\t\t\t}\n\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not save the flow', error)\n\t\t\t\tthis.error = error\n\t\t\t\treturn null\n\t\t\t} finally {\n\t\t\t\tthis.saving = false\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Publish the open flow's draft, so it backs new runs.\n\t\t *\n\t\t * Runs already in flight are untouched: they are pinned to the version\n\t\t * they started on, which is the whole point of publishing being an\n\t\t * event rather than a save.\n\t\t *\n\t\t * @param {string|null} bump The semver component to advance ('major' |\n\t\t * 'minor' | 'patch'), or null to let the server\n\t\t * decide from what actually changed.\n\t\t * @return {Promise<object|null>} The published version, or null.\n\t\t */\n\t\tasync publish(bump = null) {\n\t\t\treturn await this.transition('publish', (bump ? { bump } : null))\n\t\t},\n\n\t\t/**\n\t\t * Ask what publishing would be called, without publishing.\n\t\t *\n\t\t * A GET that changes nothing. The author is asking before they commit\n\t\t * to an answer, so a refusal here would make it impossible to find out\n\t\t * that a change is breaking without first asserting that it is not.\n\t\t *\n\t\t * @return {Promise<object|null>} The preview, or null when it could not\n\t\t * be fetched.\n\t\t */\n\t\tasync previewPublish() {\n\t\t\tif (!this.flow.id) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\tthis.previewingPublish = true\n\t\t\tthis.versionBumpRefusal = null\n\n\t\t\ttry {\n\t\t\t\tconst response = await axios.get(generateUrl(`/apps/openregister/api/flows/${this.flow.id}/version-preview`))\n\t\t\t\tthis.publishPreview = response.data || null\n\t\t\t\treturn this.publishPreview\n\t\t\t} catch (error) {\n\t\t\t\t// 🔑 A PREVIEW THAT FAILS MUST NOT BLOCK THE PUBLISH. It is a\n\t\t\t\t// courtesy, and an instance whose route is older than this\n\t\t\t\t// build would otherwise lose the ability to publish at all.\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not preview the next version', error)\n\t\t\t\tthis.publishPreview = null\n\t\t\t\treturn null\n\t\t\t} finally {\n\t\t\t\tthis.previewingPublish = false\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Create a draft version from the published one.\n\t\t *\n\t\t * The published version keeps serving until the draft is published, so\n\t\t * editing a live process never takes it offline.\n\t\t *\n\t\t * @return {Promise<object|null>} The new draft version, or null.\n\t\t */\n\t\tasync createDraft() {\n\t\t\treturn await this.transition('draft')\n\t\t},\n\n\t\t/**\n\t\t * Retire the published version, so the flow backs no new runs.\n\t\t *\n\t\t * @return {Promise<object|null>} The deprecated version, or null.\n\t\t */\n\t\tasync deprecate() {\n\t\t\treturn await this.transition('deprecate')\n\t\t},\n\n\t\t/**\n\t\t * POST one lifecycle transition and reload the flow it changed.\n\t\t *\n\t\t * 🔑 THE RELOAD IS NOT OPTIONAL. A transition changes `version` and\n\t\t * `lifecycleStatus`, and those decide whether the canvas is editable.\n\t\t * Leaving the client's copy stale would show an author an editable\n\t\t * canvas over a version the server will refuse to write.\n\t\t *\n\t\t * @param {string} action `publish`, `draft` or `deprecate`.\n\t\t * @param {object|null} body What to send with it, such as `{bump}`.\n\t\t * @return {Promise<object|null>} The resulting version, or null.\n\t\t */\n\t\tasync transition(action, body = null) {\n\t\t\tif (!this.flow.id) {\n\t\t\t\tthis.error = new Error('Save the flow before changing its lifecycle.')\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\tthis.transitioning = true\n\t\t\tthis.lifecycleRefusal = null\n\t\t\tthis.versionBumpRefusal = null\n\n\t\t\ttry {\n\t\t\t\t// 🔑 NO BODY MEANS NO SECOND ARGUMENT. `draft` and `deprecate`\n\t\t\t\t// take nothing, and sending them an empty object changes the\n\t\t\t\t// call every caller and test has ever seen for the sake of a\n\t\t\t\t// parameter only `publish` uses.\n\t\t\t\tconst url = generateUrl(`/apps/openregister/api/flows/${this.flow.id}/${action}`)\n\t\t\t\tconst response = body\n\t\t\t\t\t? await axios.post(url, body)\n\t\t\t\t\t: await axios.post(url)\n\n\t\t\t\t// RELOAD THE LIST FIRST. `open()` reads from `this.flows`, not\n\t\t\t\t// from the server, so opening without reloading would restore\n\t\t\t\t// the pre-transition copy and show a published flow as still a\n\t\t\t\t// draft — with an editable canvas over it.\n\t\t\t\tconst id = this.flow.id\n\t\t\t\tconst app = this.flow.app\n\t\t\t\tawait this.load({ app })\n\t\t\t\tthis.open(id, app)\n\t\t\t\tawait this.loadVersions()\n\n\t\t\t\treturn response.data || null\n\t\t\t} catch (error) {\n\t\t\t\tif (error?.response?.status === 409) {\n\t\t\t\t\t// 🔑 TWO DIFFERENT 409s. `version-bump-refused` means the\n\t\t\t\t\t// flow is fine and the REQUEST was wrong — the author asked\n\t\t\t\t\t// to call a removal minor — and its remedy is to publish it\n\t\t\t\t\t// as major, not to create a draft. Reading both as a\n\t\t\t\t\t// lifecycle refusal offers the wrong button.\n\t\t\t\t\tif (error.response.data?.kind === 'version-bump-refused') {\n\t\t\t\t\t\tthis.versionBumpRefusal = error.response.data?.error || null\n\t\t\t\t\t\treturn null\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.lifecycleRefusal = {\n\t\t\t\t\t\treason: error.response.data?.reason || null,\n\t\t\t\t\t\tlifecycleStatus: error.response.data?.lifecycleStatus || null,\n\t\t\t\t\t}\n\t\t\t\t\treturn null\n\t\t\t\t}\n\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error(`cn-flow: could not ${action} the flow`, error)\n\t\t\t\tthis.error = error\n\t\t\t\treturn null\n\t\t\t} finally {\n\t\t\t\tthis.transitioning = false\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Load every version of the open flow, newest first.\n\t\t *\n\t\t * @return {Promise<Array>} The versions.\n\t\t */\n\t\tasync loadVersions() {\n\t\t\tif (!this.flow.id) {\n\t\t\t\tthis.versions = []\n\t\t\t\treturn this.versions\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst response = await axios.get(generateUrl(`/apps/openregister/api/flows/${this.flow.id}/versions`))\n\t\t\t\tthis.versions = response.data?.results || []\n\t\t\t} catch (error) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not read the flow versions', error)\n\t\t\t\tthis.versions = []\n\t\t\t}\n\n\t\t\treturn this.versions\n\t\t},\n\n\t\t/**\n\t\t * Delete a flow, then reload the list.\n\t\t *\n\t\t * The reload scope matters: the editor deletes the OPEN flow, so\n\t\t * `this.flow.app` is the right scope there — but an index page deletes\n\t\t * a ROW while no flow is open, and `this.flow.app` is then blank,\n\t\t * which reloads EVERY app's flows into a list that was scoped to one.\n\t\t * Callers that know their scope pass it; the default keeps the\n\t\t * editor's behaviour.\n\t\t *\n\t\t * @param {string} id The flow id or uuid.\n\t\t * @param {object} [options] Reload options.\n\t\t * @param {string|null} [options.app] The app scope to reload with;\n\t\t * when omitted, the open flow's app is used.\n\t\t * @return {Promise<void>} Resolves when deleted and reloaded.\n\t\t */\n\t\tasync remove(id, options = {}) {\n\t\t\tawait axios.delete(generateUrl(`/apps/openregister/api/flows/${id}`))\n\t\t\tconst app = ('app' in options) ? options.app : this.flow.app\n\t\t\tawait this.load({ app })\n\t\t},\n\n\t\t/**\n\t\t * Copy a stored flow under a new name, then reload the list.\n\t\t *\n\t\t * Reads the STORED flow (`GET /api/flows/{id}`) rather than trusting a\n\t\t * list row, and re-posts its editable fields. Identity and lifecycle\n\t\t * are deliberately not copied: `FlowController::create()`'s allowlist\n\t\t * would refuse them anyway (owner is stamped from the session,\n\t\t * lifecycle starts fresh), but stripping them here documents that a\n\t\t * copy is a NEW flow — same graph, nobody's history.\n\t\t *\n\t\t * @param {string} id The flow to copy.\n\t\t * @param {string} name The copy's name.\n\t\t * @param {object} [options] Reload options.\n\t\t * @param {string|null} [options.app] The app scope to reload with.\n\t\t * @return {Promise<object>} The created flow.\n\t\t */\n\t\tasync duplicate(id, name, options = {}) {\n\t\t\tconst response = await axios.get(generateUrl(`/apps/openregister/api/flows/${id}`))\n\t\t\tconst {\n\t\t\t\tid: _id,\n\t\t\t\tuuid: _uuid,\n\t\t\t\towner: _owner,\n\t\t\t\torganisation: _organisation,\n\t\t\t\tcreated: _created,\n\t\t\t\tupdated: _updated,\n\t\t\t\tlifecycleStatus: _lifecycleStatus,\n\t\t\t\tversion: _version,\n\t\t\t\t...editable\n\t\t\t} = response.data || {}\n\t\t\tconst createResponse = await axios.post(\n\t\t\t\tgenerateUrl('/apps/openregister/api/flows'),\n\t\t\t\t{ ...editable, name },\n\t\t\t)\n\t\t\tconst app = ('app' in options) ? options.app : this.flow.app\n\t\t\tawait this.load({ app })\n\t\t\treturn createResponse.data\n\t\t},\n\n\t\t/**\n\t\t * Run the stored flow, immediately or queued, as the flow itself says.\n\t\t *\n\t\t * A flow must be SAVED before it runs. The engine walks the stored\n\t\t * document, so running unsaved canvas state would report on a graph that\n\t\t * is not the one on screen.\n\t\t *\n\t\t * 🔴 `executionMode` DECIDES, AND IT WAS NEVER SENT. This POST carried\n\t\t * only the subject, so the endpoint fell back to its async default and\n\t\t * every press of Run produced a row reading `queued` — including for a\n\t\t * flow the author had explicitly set to run synchronously. The endpoint\n\t\t * has accepted `sync` all along; nothing was asking for it.\n\t\t *\n\t\t * A sync run answers with the FINISHED run rather than a queued one,\n\t\t * which is what a person standing in front of the button expects. An\n\t\t * async flow still queues, because that is what async means.\n\t\t *\n\t\t * @param {object} subject `{uuid, register, schema}` of the subject.\n\t\t * @return {Promise<object|null>} The run, finished or queued.\n\t\t */\n\t\tasync run(subject = {}) {\n\t\t\tif (!this.flow.id) {\n\t\t\t\tthis.error = new Error('Save the flow before running it.')\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\tthis.running = true\n\t\t\ttry {\n\t\t\t\tconst response = await axios.post(\n\t\t\t\t\tgenerateUrl(`/apps/openregister/api/flows/${this.flow.id}/run`),\n\t\t\t\t\t{ subject, sync: this.runsSynchronously },\n\t\t\t\t)\n\t\t\t\tawait this.loadRuns(this.flow.id)\n\n\t\t\t\t// The POST answers with the created run, uuid included. That\n\t\t\t\t// uuid used to be discarded, which is why pressing Run left a\n\t\t\t\t// perfectly still canvas: nothing ever looked at the run again\n\t\t\t\t// until the user opened the Runs tab. Watching it is what puts\n\t\t\t\t// the run ON the canvas.\n\t\t\t\tconst run = response.data || null\n\t\t\t\tif (run?.uuid) {\n\t\t\t\t\tthis.watchRun(run.uuid)\n\t\t\t\t}\n\n\t\t\t\treturn run\n\t\t\t} catch (error) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not run the flow', error)\n\t\t\t\tthis.error = error\n\t\t\t\treturn null\n\t\t\t} finally {\n\t\t\t\tthis.running = false\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Watch one run: poll it while its status is non-terminal.\n\t\t *\n\t\t * Polls `GET /apps/openregister/api/flow-runs/{uuid}` on an interval\n\t\t * (default 3s, floored at 2s), stops by itself on a terminal status,\n\t\t * on a re-watch, and on teardown. Pauses while the document is hidden\n\t\t * and resumes with one immediate fetch when it becomes visible — the\n\t\t * behaviour CnFlowRunsWidget already ships.\n\t\t *\n\t\t * Polling, not push, because that is what exists: the flow-run API is\n\t\t * REST only, and the engine persists the log once per worker pass\n\t\t * anyway, so a push channel would today deliver the same bursts.\n\t\t *\n\t\t * @param {string} uuid The run to watch.\n\t\t * @param {object} options Watch options.\n\t\t * @param {number} options.intervalMs Poll interval in ms; floored at 2000.\n\t\t * @return {void}\n\t\t */\n\t\twatchRun(uuid, { intervalMs = WATCH_INTERVAL_DEFAULT_MS } = {}) {\n\t\t\tthis.stopWatching()\n\n\t\t\tif (!uuid) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.watchedRunUuid = uuid\n\t\t\tthis.watchedRun = null\n\t\t\tthis.watchedSteps = []\n\t\t\tthis.watchedNewFrom = 0\n\t\t\tthis.watching = true\n\n\t\t\tconst requested = Number(intervalMs)\n\t\t\tthis._watchIntervalMs = Math.max(\n\t\t\t\tWATCH_INTERVAL_FLOOR_MS,\n\t\t\t\tNumber.isFinite(requested) ? requested : WATCH_INTERVAL_DEFAULT_MS,\n\t\t\t)\n\n\t\t\t// Bound so removeEventListener gets the SAME function back — an\n\t\t\t// inline arrow here could be added but never removed.\n\t\t\tthis._watchOnVisibility = () => this.onWatchVisibilityChange()\n\t\t\tdocument.addEventListener('visibilitychange', this._watchOnVisibility)\n\n\t\t\tthis.fetchWatchedRun()\n\t\t\tthis.startWatchTimer()\n\t\t},\n\n\t\t/**\n\t\t * Start (or restart) the poll interval — unless the watch is over or\n\t\t * the tab is hidden, in which case the visibility handler restarts it.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tstartWatchTimer() {\n\t\t\tthis.clearWatchTimer()\n\n\t\t\tif (this.watching !== true || document.hidden === true) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis._watchTimer = setInterval(() => {\n\t\t\t\tthis.fetchWatchedRun()\n\t\t\t}, this._watchIntervalMs)\n\t\t},\n\n\t\t/**\n\t\t * Clear the poll interval. The watch itself stays what it was.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tclearWatchTimer() {\n\t\t\tif (this._watchTimer !== undefined && this._watchTimer !== null) {\n\t\t\t\tclearInterval(this._watchTimer)\n\t\t\t\tthis._watchTimer = null\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * One poll of the watched run.\n\t\t *\n\t\t * Appends the log entries beyond what `watchedSteps` already holds —\n\t\t * the log only grows within a run, so the index diff is exact and an\n\t\t * already-exposed step is never replayed. Stops the watch when the\n\t\t * status turns terminal, keeping the final run and steps for the\n\t\t * canvas's last paint.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync fetchWatchedRun() {\n\t\t\tconst uuid = this.watchedRunUuid\n\t\t\tif (!uuid) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst response = await axios.get(generateUrl(`/apps/openregister/api/flow-runs/${uuid}`))\n\n\t\t\t\t// A re-watch can land while this request is in the air; its\n\t\t\t\t// answer describes a run nobody is watching any more.\n\t\t\t\tif (this.watchedRunUuid !== uuid) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tconst run = response.data || null\n\t\t\t\tthis.watchedRun = run\n\n\t\t\t\tconst log = Array.isArray(run?.log) ? run.log : []\n\t\t\t\tthis.watchedNewFrom = this.watchedSteps.length\n\t\t\t\tif (log.length > this.watchedSteps.length) {\n\t\t\t\t\tthis.watchedSteps = [\n\t\t\t\t\t\t...this.watchedSteps,\n\t\t\t\t\t\t...log.slice(this.watchedSteps.length),\n\t\t\t\t\t]\n\t\t\t\t}\n\n\t\t\t\tif (run !== null && FLOW_RUN_ACTIVE_STATUSES.includes(run.status) === false) {\n\t\t\t\t\tthis.stopWatching()\n\n\t\t\t\t\t// The Runs tab lists this run with the status it had when\n\t\t\t\t\t// the list was last read — usually `queued`. Refresh so the\n\t\t\t\t\t// history agrees with the canvas about how it ended.\n\t\t\t\t\tif (this.flow.id) {\n\t\t\t\t\t\tthis.loadRuns(this.flow.id)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not read the watched run', error)\n\n\t\t\t\t// A missing run will not come back; anything else (a blip, a\n\t\t\t\t// timeout) is worth the next poll.\n\t\t\t\tif (error?.response?.status === 404) {\n\t\t\t\t\tthis.stopWatching()\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Stop polling. The watched run and its steps are KEPT — the canvas's\n\t\t * final paint reads them — only the loop and its listener go.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tstopWatching() {\n\t\t\tthis.clearWatchTimer()\n\n\t\t\tif (this._watchOnVisibility !== undefined && this._watchOnVisibility !== null) {\n\t\t\t\tdocument.removeEventListener('visibilitychange', this._watchOnVisibility)\n\t\t\t\tthis._watchOnVisibility = null\n\t\t\t}\n\n\t\t\tthis.watching = false\n\t\t},\n\n\t\t/**\n\t\t * Pause the poll while the tab is hidden; refetch once and resume when\n\t\t * it comes back, so returning shows current state rather than whatever\n\t\t * was true when the tab was backgrounded.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tonWatchVisibilityChange() {\n\t\t\tif (document.hidden === true) {\n\t\t\t\tthis.clearWatchTimer()\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (this.watching !== true) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.fetchWatchedRun()\n\t\t\tthis.startWatchTimer()\n\t\t},\n\n\t\t/**\n\t\t * Ask the canvas to replay the inspected run's stored log.\n\t\t *\n\t\t * The steps are already here — `inspectRun()` fetched them — so this\n\t\t * only raises the token the canvas half watches. A live watch is\n\t\t * stopped first: a replay and a live run cannot share the canvas.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\trequestReplay() {\n\t\t\tif (!this.inspectedRunUuid || this.steps.length === 0) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.stopWatching()\n\t\t\tthis.replayUuid = this.inspectedRunUuid\n\t\t\tthis.replayToken += 1\n\t\t},\n\n\t\t/**\n\t\t * Load the last run and the runs-since count of each listed flow.\n\t\t *\n\t\t * One request for the whole list. A failure leaves the summary empty,\n\t\t * so the cells read \"never run\" rather than stale numbers.\n\t\t *\n\t\t * @param {Array<string>} flowIds The flows to summarise.\n\t\t * @param {string} since ISO 8601 moment the count starts at.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync loadRunSummary(flowIds, since) {\n\t\t\tconst ids = (flowIds || []).filter(Boolean)\n\t\t\tif (ids.length === 0) {\n\t\t\t\tthis.runSummary = {}\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst response = await axios.get(generateUrl('/apps/openregister/api/flow-runs/summary'), {\n\t\t\t\t\tparams: { flowIds: ids.join(','), since },\n\t\t\t\t})\n\t\t\t\tthis.runSummary = response.data?.results || {}\n\t\t\t} catch (error) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not load the run summary', error)\n\t\t\t\tthis.runSummary = {}\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Load the runs of the given flows since a moment, newest first.\n\t\t *\n\t\t * @param {Array<string>} flowIds The flows whose runs to list.\n\t\t * @param {string} since ISO 8601 moment the list starts at.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync loadRecentRuns(flowIds, since) {\n\t\t\tconst ids = (flowIds || []).filter(Boolean)\n\t\t\tif (ids.length === 0) {\n\t\t\t\tthis.recentRuns = []\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.recentRunsLoading = true\n\t\t\ttry {\n\t\t\t\tconst response = await axios.get(generateUrl('/apps/openregister/api/flow-runs'), {\n\t\t\t\t\tparams: { flowIds: ids.join(','), since, limit: 200 },\n\t\t\t\t})\n\t\t\t\tthis.recentRuns = response.data?.results || []\n\t\t\t} catch (error) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not load recent runs', error)\n\t\t\t\tthis.recentRuns = []\n\t\t\t} finally {\n\t\t\t\tthis.recentRunsLoading = false\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Switch a stored flow on or off from a list, without opening it.\n\t\t *\n\t\t * Reads the stored flow and writes it back whole with only `enabled`\n\t\t * changed, the same round trip `duplicate()` makes: a partial body\n\t\t * would be read as a document without nodes. The list row is updated\n\t\t * in place from the answer, so the toggle does not reload the list.\n\t\t *\n\t\t * @param {string} id The flow id or uuid.\n\t\t * @param {boolean} enabled The new state.\n\t\t * @return {Promise<object>} The saved flow.\n\t\t */\n\t\tasync setEnabled(id, enabled) {\n\t\t\tconst current = await axios.get(generateUrl(`/apps/openregister/api/flows/${id}`))\n\t\t\tconst response = await axios.put(\n\t\t\t\tgenerateUrl(`/apps/openregister/api/flows/${id}`),\n\t\t\t\t{ ...(current.data || {}), enabled: enabled === true },\n\t\t\t)\n\t\t\tconst saved = response.data || {}\n\t\t\tconst now = typeof saved.enabled === 'boolean' ? saved.enabled : enabled === true\n\t\t\tthis.flows = this.flows.map((flow) => (\n\t\t\t\tString(flow.id) === String(id) || String(flow.uuid) === String(id)\n\t\t\t\t\t? { ...flow, enabled: now }\n\t\t\t\t\t: flow\n\t\t\t))\n\t\t\treturn saved\n\t\t},\n\n\t\t/**\n\t\t * Start a finished run again, as `POST /api/flow-runs/{uuid}/retry`.\n\t\t *\n\t\t * @param {string} uuid The run to retry.\n\t\t * @return {Promise<object|null>} The new run, or null without a uuid.\n\t\t */\n\t\tasync retryRun(uuid) {\n\t\t\tif (!uuid) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst response = await axios.post(generateUrl(`/apps/openregister/api/flow-runs/${encodeURIComponent(uuid)}/retry`))\n\t\t\tif (this.flow.id) {\n\t\t\t\tawait this.loadRuns(this.flow.id)\n\t\t\t}\n\t\t\treturn response.data || null\n\t\t},\n\n\t\tasync loadRuns(flowId) {\n\t\t\ttry {\n\t\t\t\tconst response = await axios.get(generateUrl('/apps/openregister/api/flow-runs'), {\n\t\t\t\t\tparams: { flowId, limit: 25 },\n\t\t\t\t})\n\t\t\t\tthis.runs = response.data?.results || []\n\t\t\t} catch (error) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not load run history', error)\n\t\t\t\tthis.runs = []\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Load one run's per-node steps.\n\t\t *\n\t\t * This is what the step table exists for — the run's aggregate log\n\t\t * cannot answer \"which node produced this\" without being walked.\n\t\t *\n\t\t * @param {string} runUuid The run to inspect.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync inspectRun(runUuid) {\n\t\t\tthis.inspectedRunUuid = runUuid\n\t\t\tlet version = null\n\t\t\ttry {\n\t\t\t\tconst response = await axios.get(generateUrl(`/apps/openregister/api/flow-runs/${runUuid}`))\n\t\t\t\t// KEPT WHOLE, not picked apart. The record carries the run's\n\t\t\t\t// status, its error, and the objects it is about, none of which\n\t\t\t\t// can be recovered from the log or from the capped history list.\n\t\t\t\tthis.runDetail = response.data || null\n\t\t\t\tthis.steps = response.data?.log || []\n\t\t\t\t// Read from the RUN, not from `this.runs`. A run reached by\n\t\t\t\t// `?run=` need not be in the loaded page of run history at all —\n\t\t\t\t// the history is capped at 25 — and the run's own record is the\n\t\t\t\t// authority on which version of the flow it executed.\n\t\t\t\tversion = response.data?.flowVersion ?? null\n\t\t\t} catch (error) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not load the run steps', error)\n\t\t\t\tthis.runDetail = null\n\t\t\t\tthis.steps = []\n\t\t\t}\n\n\t\t\t// BEFORE the objects and tasks: those two only fill panels, while\n\t\t\t// this changes what the canvas is showing, and a reader watching the\n\t\t\t// graph swap after the panels have settled reads it as a glitch.\n\t\t\tawait this.showRunVersionGraph(version)\n\n\t\t\t// Loaded alongside the steps, not on demand behind another click.\n\t\t\t// The steps say what the run DID; these say what it did it TO, and\n\t\t\t// reading one without the other is the gap this exists to close.\n\t\t\tawait this.loadRunObjects(runUuid)\n\t\t\tawait this.loadRunTasks(runUuid)\n\t\t},\n\n\t\t/**\n\t\t * Put the graph a run actually executed onto the canvas.\n\t\t *\n\t\t * The version's stored graph replaces `flow.nodes`/`flow.edges` for as\n\t\t * long as the run is open. The displaced graph is stashed in `liveGraph`\n\t\t * so `closeRun()` can put it back exactly — refetching instead would\n\t\t * lose an author's in-progress layout for no gain.\n\t\t *\n\t\t * 🔴 UNSAVED WORK IS NEVER DISPLACED. `dirty` means the author has edits\n\t\t * on this canvas that exist nowhere else. Swapping the graph out from\n\t\t * under them would destroy those edits with no undo and no warning, to\n\t\t * show a nicety. So a dirty canvas keeps its graph and the run replays\n\t\t * over it, exactly as it did before this existed, and CnFlowDetail says\n\t\t * so on the canvas rather than leaving the reader to guess which graph\n\t\t * they are looking at.\n\t\t *\n\t\t * A version that cannot be read — pruned, or never recorded for a run\n\t\t * from before versioning — is recorded in `runGraphNotice` and\n\t\t * the replay falls back to the live graph. That fallback is the OLD\n\t\t * behaviour, so nothing regresses; it just stops being silent.\n\t\t *\n\t\t * @param {number|string|null} version The run's `flowVersion`.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync showRunVersionGraph(version) {\n\t\t\tthis.runGraphNotice = null\n\n\t\t\tconst number = Number(version)\n\t\t\tif (!this.flow.id || !Number.isInteger(number) || number <= 0) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (this.dirty === true) {\n\t\t\t\tthis.runGraphNotice = { version: number, reason: 'unsaved-edits' }\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst response = await axios.get(generateUrl(`/apps/openregister/api/flows/${this.flow.id}/versions/${number}`))\n\t\t\t\tconst graph = response.data?.graph\n\t\t\t\tif (!graph || Array.isArray(graph.nodes) === false) {\n\t\t\t\t\tthis.runGraphNotice = { version: number, reason: 'unreadable' }\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// Stashed ONCE. Moving between two runs of the same flow calls\n\t\t\t\t// this twice, and overwriting the stash on the second call would\n\t\t\t\t// store the FIRST run's snapshot as the live graph — after\n\t\t\t\t// which closing the run restores a version instead of the flow.\n\t\t\t\tif (this.liveGraph === null) {\n\t\t\t\t\tthis.liveGraph = {\n\t\t\t\t\t\tnodes: this.flow.nodes,\n\t\t\t\t\t\tedges: this.flow.edges,\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tthis.flow = {\n\t\t\t\t\t...this.flow,\n\t\t\t\t\t// Deep-copied for the same reason `open()` deep-copies the\n\t\t\t\t\t// list row: the canvas mutates node positions, and a stored\n\t\t\t\t\t// version is not the place to discover that.\n\t\t\t\t\tnodes: JSON.parse(JSON.stringify(graph.nodes)),\n\t\t\t\t\tedges: Array.isArray(graph.edges) ? JSON.parse(JSON.stringify(graph.edges)) : [],\n\t\t\t\t}\n\t\t\t\tthis.viewingVersion = number\n\n\t\t\t\t// A stored version carries whatever coordinates it was saved\n\t\t\t\t// with, and a flow imported from `x-openregister-flows` was\n\t\t\t\t// saved with none — so the same pile `open()` guards against\n\t\t\t\t// arrives here by a different route.\n\t\t\t\tthis.applyRenderLayout()\n\t\t\t} catch (error) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not read the graph this run executed', error)\n\t\t\t\tthis.runGraphNotice = { version: number, reason: 'unreadable' }\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Stop inspecting a run and put the live graph back.\n\t\t *\n\t\t * The one way out, so the restore cannot be forgotten. Setting\n\t\t * `inspectedRunUuid = null` by hand would leave a historic graph on a\n\t\t * canvas that no longer says it is historic — and, because the lock\n\t\t * lifts with `viewingVersion`, an editable one.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tcloseRun() {\n\t\t\tthis.inspectedRunUuid = null\n\t\t\tthis.runDetail = null\n\t\t\t// The other half of run view. Leaving it set would keep every\n\t\t\t// surface in run view after the reader asked to go back to the flow,\n\t\t\t// and the canvas would keep saying the run was still opening.\n\t\t\tthis.openingRunUuid = null\n\t\t\tthis.steps = []\n\t\t\tthis.runObjects = []\n\t\t\tthis.runTasks = []\n\t\t\tthis.replayUuid = null\n\t\t\tthis.runGraphNotice = null\n\n\t\t\tif (this.liveGraph !== null) {\n\t\t\t\tthis.flow = {\n\t\t\t\t\t...this.flow,\n\t\t\t\t\tnodes: this.liveGraph.nodes,\n\t\t\t\t\tedges: this.liveGraph.edges,\n\t\t\t\t}\n\t\t\t\tthis.liveGraph = null\n\t\t\t}\n\n\t\t\tthis.viewingVersion = null\n\t\t},\n\n\t\t/**\n\t\t * Load the tasks one run raised.\n\t\t *\n\t\t * 🔴 AN EMPTY UUID IS NOT A QUERY, AND THE SERVER WILL NOT SAVE US.\n\t\t * `?runUuid=` is treated as ABSENT, and an absent anchor means the\n\t\t * endpoint answers with the caller's ordinary inbox. Sending one would\n\t\t * put somebody's own task list under a run's Tasks tab, so the guard is\n\t\t * here rather than a hope that an empty answer comes back.\n\t\t *\n\t\t * 🔴 THE RESPONSE IS CHECKED AGAINST THE RUN, NOT TRUSTED. The anchor\n\t\t * is merged (openregister `801cc02b`), but this is a LIBRARY: a\n\t\t * consuming app can be running an openregister from before it, where an\n\t\t * unknown query parameter is silently dropped rather than rejected. That\n\t\t * server returns a perfectly valid 200 full of the reader's own tasks,\n\t\t * and rendering it would be a disclosure dressed as a feature with\n\t\t * nothing failing anywhere. Rows that do not name this run are dropped;\n\t\t * against an old server that empties the tab, which is the honest\n\t\t * answer.\n\t\t *\n\t\t * `scope` is deliberately NOT sent. The anchor overrides it, so passing\n\t\t * one would be a parameter that reads as though it narrowed something.\n\t\t *\n\t\t * @param {string} runUuid The run to read.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync loadRunTasks(runUuid) {\n\t\t\tif (!runUuid) {\n\t\t\t\tthis.runTasks = []\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst response = await axios.get(generateUrl('/apps/openregister/api/flow-tasks'), {\n\t\t\t\t\tparams: { runUuid },\n\t\t\t\t})\n\n\t\t\t\tconst rows = response.data?.results || []\n\t\t\t\tthis.runTasks = rows.filter((task) => String(task?.runUuid || '') === String(runUuid))\n\t\t\t} catch (error) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not load the tasks this run raised', error)\n\t\t\t\tthis.runTasks = []\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Load the objects one run touched, grouped by the node that touched them.\n\t\t *\n\t\t * A run's own record names only the object that TRIGGERED it, so\n\t\t * everything it went on to create or change is answerable only from the\n\t\t * attribution stamped on the audit trail. This is that read.\n\t\t *\n\t\t * Failure is quiet and empties the list rather than leaving the previous\n\t\t * run's objects on screen — stale rows here would be read as \"this run\n\t\t * touched those\", which is worse than showing nothing.\n\t\t *\n\t\t * @param {string} runUuid The run to read.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync loadRunObjects(runUuid) {\n\t\t\ttry {\n\t\t\t\tconst response = await axios.get(generateUrl(`/apps/openregister/api/flow-runs/${runUuid}/objects`))\n\t\t\t\tthis.runObjects = response.data?.nodes || []\n\t\t\t} catch (error) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('cn-flow: could not load the objects this run touched', error)\n\t\t\t\tthis.runObjects = []\n\t\t\t}\n\t\t},\n\t},\n})\n"],"names":["axios","t"],"mappings":";;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAC;AAClE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACY,MAAC,wBAAwB,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAC;AAC1E;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,yBAAyB,GAAG,KAAI;AACtC,MAAM,uBAAuB,GAAG,KAAI;AACpC;AACA,SAAS,SAAS,GAAG;AACrB,CAAC,OAAO;AACR,EAAE,IAAI,EAAE,EAAE;AACV,EAAE,WAAW,EAAE,EAAE;AACjB,EAAE,KAAK,EAAE,EAAE;AACX,EAAE,GAAG,EAAE,cAAc;AACrB,EAAE,eAAe,EAAE,EAAE;AACrB,EAAE,aAAa,EAAE,EAAE;AACnB,EAAE,OAAO,EAAE,gBAAgB;AAC3B,EAAE,IAAI,EAAE,EAAE;AACV,EAAE,aAAa,EAAE,OAAO;AACxB,EAAE,OAAO,EAAE,KAAK;AAChB,EAAE,KAAK,EAAE,EAAE;AACX,EAAE,KAAK,EAAE,EAAE;AACX,EAAE,MAAM,EAAE,EAAE;AACZ,EAAE,aAAa,EAAE,IAAI;AACrB,EAAE,YAAY,EAAE,IAAI;AACpB,EAAE,gBAAgB,EAAE,IAAI;AACxB;AACA;AACA;AACA;AACA,EAAE,OAAO,EAAE,CAAC;AACZ,EAAE,eAAe,EAAE,OAAO;AAC1B,EAAE;AACF,CAAC;AACD;AACY,MAAC,YAAY,GAAG,WAAW,CAAC,QAAQ,EAAE;AAClD,CAAC,KAAK,EAAE,OAAO;AACf,EAAE,IAAI,EAAE,SAAS,EAAE;AACnB,EAAE,KAAK,EAAE,EAAE;AACX;AACA;AACA;AACA,EAAE,eAAe,EAAE,OAAO;AAC1B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAE,SAAS,EAAE,EAAE;AACf,EAAE,cAAc,EAAE,IAAI;AACtB,EAAE,eAAe,EAAE,IAAI;AACvB;AACA;AACA;AACA;AACA,EAAE,aAAa,EAAE,IAAI;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAE,WAAW,EAAE,IAAI;AACnB;AACA;AACA;AACA;AACA;AACA;AACA,EAAE,kBAAkB,EAAE,IAAI;AAC1B;AACA;AACA;AACA;AACA,EAAE,WAAW,EAAE,IAAI;AACnB;AACA;AACA,EAAE,QAAQ,EAAE,EAAE;AACd;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAE,gBAAgB,EAAE,IAAI;AACxB;AACA;AACA,EAAE,aAAa,EAAE,KAAK;AACtB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAE,cAAc,EAAE,IAAI;AACtB;AACA;AACA,EAAE,iBAAiB,EAAE,KAAK;AAC1B;AACA;AACA;AACA;AACA,EAAE,kBAAkB,EAAE,IAAI;AAC1B;AACA;AACA;AACA;AACA,EAAE,WAAW,EAAE,EAAE;AACjB,EAAE,YAAY,EAAE,EAAE;AAClB;AACA;AACA;AACA;AACA;AACA,EAAE,cAAc,EAAE,KAAK;AACvB;AACA;AACA;AACA,EAAE,UAAU,EAAE,EAAE;AAChB;AACA;AACA;AACA,EAAE,UAAU,EAAE,EAAE;AAChB,EAAE,iBAAiB,EAAE,KAAK;AAC1B;AACA;AACA;AACA,EAAE,IAAI,EAAE,EAAE;AACV,EAAE,KAAK,EAAE,EAAE;AACX;AACA;AACA;AACA;AACA,EAAE,UAAU,EAAE,EAAE;AAChB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAE,QAAQ,EAAE,EAAE;AACd,EAAE,gBAAgB,EAAE,IAAI;AACxB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAE,SAAS,EAAE,IAAI;AACjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AA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"}
|