Storing a workflow drops the editor's scratch state
A canvas carries state that means something while someone is looking at it and nothing afterwards. Storing the workflow is where that state is dropped, which is why a client reading back what it just wrote does not get it back.
The rule
- Storing a workflow discards the transient state an editor keeps on a node while it is being edited:
selected,dragging,deletable, andnodeIdboth on the node and inside the node'sdata. - It also reduces a node's
data.metadatato the node type the node anchors to; the rest of the metadata is not stored, because it is restored from the node type on read (STORE-14). - A node's
measuredandposition, and itsdata.config,data.labelanddata.extensions, survive the write unchanged. - A node whose node-type anchor does not resolve is exempt: it keeps its metadata and its
typeverbatim, since nothing could restore them on read. - Discarding is idempotent, so storing an already-stored workflow drops nothing further.
What it means
An editor keeps state that only means something while a person is looking at it — which node is selected, which is mid-drag, whether it can currently be deleted. Storing the workflow is where that state is thrown away, which is why reading back what was just written does not return it: it was never kept in the first place.
The same write also trims a node's own metadata down to the one thing
storage needs to find the node's type again. Everything else in that
metadata is not lost so much as not this layer's problem: it is rebuilt from
the type on read (STORE-14). That rebuilding is what makes the trim safe —
and it is also what makes the one exception necessary. A node whose declared
type cannot be resolved has nothing to rebuild from, so trimming its
metadata would destroy information with no way back. That node keeps its
metadata, and its own type, exactly as sent.
Doing this twice changes nothing the second time: a workflow that has already been through this write has nothing left in it for the write to find.
Example
Two nodes sent in the same shape, one with a type the store can resolve and one without.
POST /api/flowdrop/workflows
{"id": "wf", "name": "WF", "nodes": [{"id": "calculator.1", "type": "universalNode", "position": {"x": 900, "y": 200}, "data": {"label": "E2E Calculator", "config": {"operation": "add"}, "metadata": {"id": "calculator", "name": "Derived Name"}, "nodeId": "calculator.1"}, "deletable": true, "measured": {"width": 290, "height": 647}, "selected": true, "dragging": false}]}POST /api/flowdrop/workflows
{"id": "wf2", "name": "WF2", "nodes": [{"id": "mystery.1", "type": "universalNode", "data": {"metadata": {"name": "Hand written", "inputs": []}, "nodeId": "mystery.1"}, "selected": true}]}The first node keeps its position, measured and data.config unchanged,
loses selected, dragging, deletable and data.nodeId, and has its
data.metadata reduced to {"node_type_id": "calculator"}. The second loses
the same editor-only fields, but its metadata and its type survive
untouched — there is no type to rebuild them from later, so nothing is
thrown away that could not be recovered.