Repository navigation
Relationship editing command surface + required last-edge protection (#1918) - #1993
Merged
Merged
Conversation
…ion (#1918) Wire the create/delete/update-edge paths for typed relationships end to end (proto -> daemon -> core -> Tauri), so the relationship viewer can populate edges, not just list them: - store: `update_relationship_properties` replaces an edge's `properties` JSON wholesale, bumping version/modified_at; returns None when the edge is absent - NodeService: `update_relationship_properties` (errors on a missing edge, emits RelationshipUpdated) and a `required` last-edge guard in `delete_relationship` that rejects removing the final edge of a relationship declared `required: true` (built-ins and non-last removals are unaffected) - rel_ops: `update_relationship_properties` op - proto: DeleteRelationship + UpdateRelationshipProperties RPCs and messages - daemon: handlers forwarding to rel_ops (create RPC already existed) - Tauri: `create_relationship`, `delete_relationship`, `update_relationship_properties` commands, registered in lib.rs Cardinality-One rejection was already enforced on create; this adds the delete and edit halves. Integration tests cover the edit round-trip, the missing-edge error, and required last-edge protection across add/remove sequences. Co-Authored-By: Claude <noreply@anthropic.com>
…1918) Follow-up to the adversarial review of this branch: - rel_ops create/delete/update now map NodeService errors via `OpsError::from` instead of a blanket `OpsError::Internal`, so validation rejections (required last-edge, missing edge, cardinality, wrong target type) surface as gRPC INVALID_ARGUMENT the frontend can present, not an opaque INTERNAL fault. - delete guard: warn instead of silently failing open when a schema's `relationships` array can't be parsed, and only enforce `required` for a forward (`direction: out`) relationship so an inbound declaration never counts the wrong edge set. - update_relationship_properties rejects non-object `properties` (scalar / array / null) so an edit can't replace a structured edge blob with an unexpected shape. - Add regression tests: required-last-edge delete surfaces ValidationFailed (not Internal); non-object properties are rejected and leave the edge untouched. Co-Authored-By: Claude <noreply@anthropic.com>
Contributor
Author
|
Adversarial review → addressed → APPROVE. Independent review flagged one blocker + four minors; all addressed in the follow-up commit:
The "last-edge" identification logic — the headline concern — was confirmed correct (specific-edge Verdict: APPROVE. |
Closed
18 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #1918 (relationship viewer). Follow-up to the read-only first slice (#1992). Does not close #1918 — the editable-modal UI, target picker, and view-settings remain.
What this ships
The backend command surface for editing typed relationships, end to end (proto → daemon → core → Tauri), so the viewer can populate edges rather than only list them — slice (a) editing + slice (b) enforcement:
core
SqliteStore::update_relationship_properties— replaces an edge'spropertiesJSON wholesale, bumpsversion/modified_at; returnsNonewhen the edge is absent.NodeService::update_relationship_properties— errors on a missing edge (no silent no-op), emitsRelationshipUpdated.NodeService::delete_relationship— required last-edge guard: rejects removing the final edge of a relationship declaredrequired: true. Only blocks when the targeted edge exists and it's the last one; non-last removals and built-ins are unaffected.rel_ops::update_relationship_propertiesop.proto / daemon
DeleteRelationship+UpdateRelationshipPropertiesRPCs (create RPC already existed); daemon handlers forward torel_ops.Tauri (desktop-app)
create_relationship,delete_relationship,update_relationship_propertiescommands, registered inlib.rs.Not in this PR
Cardinality-
Onerejection on create was already enforced on main; this adds the delete and edit halves. The editable modal, target-selection picker, and view-settings are separate follow-up slices.Tests
New
packages/core/tests/relationship_editing_test.rs(4 tests): edit round-trip overwrites edge attributes; update on a missing edge errors; required last-edge protection across add/remove sequences; a non-required relationship allows deleting its last edge. Fullcargo test -p nodespace-core relationshipgreen (47 tests),cargo build -p nodespace-daemon -p nodespace-appclean,cargo clippy+fmtclean. Pre-push gate (test:all + build + e2e) passed.