Symptom

Adding a node under a Project automatically set the Project as a source of the new child, and adding a Project under a Server set the Server as the Project’s source. Neither should observe its parent. An earlier client-side attempt to clear this did not cover all creation paths.

Root cause

On first creation, ServerNodeManager.update() unconditionally applied the parent-as-source creation default (withParentSourceDefault) to every new targeting node — “drop a child under a parent and it just works.” There was no carve-out for projects, so a Project (or any child of a Project) got its parent wired in as a source. Because the wiring is applied server-side at persist time, fixing it only in the client could never be authoritative: a node posted from any path (menu, avatar, import, peer sync) still hit the same server default.

Fix

Added a pure helper NodeMetaData.resolveCreatedChildWiring(nodeType, parentType, parent) in shared/.../node/NodeMetaDataSourceWiring.kt: if the node is a KrillApp.Project or its parent is a KrillApp.Project, it drops all wiring via clearedWiring() (empty sources + executionSource, nodeAction preserved); otherwise it keeps the existing withParentSourceDefault behaviour, and only when sources are still empty. It is idempotent (returns the same reference when no change is needed) so the caller’s create-time update(node.copy(meta = …)) re-entry terminates. ServerNodeManager.update() now reads the parent node’s type and calls this helper instead of the inline default — so the rule holds regardless of what the client posted (it actively clears a project source the client may have set). KrillApp.Project is a leaf object, so is KrillApp.Project matches only the container, not Project.Diagram / Camera / TaskList / Journal. Bundled with the intentional krill-sdk 0.0.27 → 0.0.29 bump.

Prevention

Source-wiring policy belongs at the single server-side persist boundary (ServerNodeManager.update() on isNewNode), not in client editors — client paths are plural and easy to miss. The decision is now one pure, unit-tested function (NodeMetaDataSourceWiringTest: child-under-project, project-under-server, client-posted-source-cleared, non-project-still-wires, plus idempotency), and the only HTTP creation route (POST /node/{id}) flows through update(). When changing creation-time wiring, change the helper + its tests, and confirm the call site in update() rather than patching individual editors.