Repository navigation
Remove parent_id/container_node_id from Node API - Complete Graph Migration #514
Description
Remove parent_id/container_node_id from Node API - Full Graph Migration
Summary
Complete the graph-native architecture migration by removing parent_id and container_node_id fields from the Node model and all API responses. Currently, these fields are populated for backward compatibility (Issue #511 partial implementation), but they should be removed to fully leverage SurrealDB's graph capabilities.
Background
Issue #511 migrated NodeSpace to a graph-native architecture using SurrealDB:
- ✅ Database layer uses graph edges (
has_child) for hierarchy - ✅ No
parent_id/container_node_idstored in database tables ⚠️ Temporary workaround:get_children()reconstructs these fields from query context for frontend compatibility
Current State (packages/core/src/db/surreal_store.rs:1307-1314):
// Populate parent_id and container_node_id for frontend compatibility
// In graph architecture, these are derived from the query context, not stored
if let Some(pid) = parent_id_value {
for node in &mut nodes {
node.parent_id = Some(pid.clone());
node.container_node_id = Some(pid.clone());
}
}This is a temporary bridge - not the elegant graph-native solution.
Problem
The current approach has several issues:
- Incomplete graph migration: Backend uses graphs, but API still exposes flat parent_id fields
- Inconsistent data model:
Nodestruct has fields that don't exist in database - Coupling: Backend reconstructs data to match old frontend expectations
- Performance: Requires extra logic to populate fields that shouldn't exist
- Missing hierarchy info: Frontend only knows immediate parent, not full ancestor chain (graphs enable this)
Proposed Solution
Phase 1: Backend Cleanup (Rust)
-
Remove fields from
Nodestruct (packages/core/src/models.rs):pub struct Node { pub id: String, pub node_type: String, pub content: String, // REMOVE: pub parent_id: Option<String>, // REMOVE: pub container_node_id: Option<String>, pub before_sibling_id: Option<String>, // ... rest of fields }
-
Remove field population (packages/core/src/db/surreal_store.rs:1307-1314):
- Delete the
parent_id/container_node_idreconstruction code inget_children() - Remove from
From<SurrealNode> for Nodeconversion (already hardcoded toNone)
- Delete the
-
Update
CreateNodeRequest(packages/desktop-app/src-tauri/src/bin/dev-proxy.rs:246):- Remove
parent_idandcontainer_node_idfields from request struct - API should accept only
parentIdin request body, use it for edge creation, then discard
- Remove
Phase 2: Frontend Migration (TypeScript/Svelte)
-
Update
Nodeinterface (packages/desktop-app/src/lib/models/node.ts):export interface Node { id: string; nodeType: string; content: string; // REMOVE: parentId?: string | null; // REMOVE: containerNodeId?: string | null; beforeSiblingId?: string | null; // ... rest of fields }
-
Update components to use context instead of
node.parentId:- Components receiving nodes from
getNodesByContainer(parentId)already know the parent - Pass parent context via component props or Svelte context API
- Example:
<BaseNodeViewer {nodes} parentId={currentPageId} />
- Components receiving nodes from
-
Key files to update:
src/lib/services/backend-adapter.ts- Remove field mappingsrc/lib/design/components/base-node-viewer.svelte- Accept parent via propsrc/lib/components/viewers/date-node-viewer.svelte- Pass parent context- Any component using
node.parentIdornode.containerNodeId
Phase 3: Enhanced Graph Features (Future)
Once fields are removed, we can add graph-native features:
- Ancestor chains:
GET /api/nodes/:id/ancestors- full parent hierarchy - Descendant trees:
GET /api/nodes/:id/descendants?depth=N- subtree queries - Sibling queries:
GET /api/nodes/:id/siblings- nodes with same parent - Graph traversal: Complex queries like "all tasks under this project, 3 levels deep"
Implementation Guide
Step 1: Search and Replace
Find all usages of these fields:
# Backend (Rust)
rg "parent_id|container_node_id" packages/core/
rg "parent_id|container_node_id" packages/desktop-app/src-tauri/
# Frontend (TypeScript/Svelte)
rg "parentId|containerNodeId" packages/desktop-app/src/Step 2: Update Each Usage
For each usage, determine:
- If creating a node: Keep
parentIdin request body for edge creation only - If reading a node: Replace with parent context from component hierarchy
- If checking hierarchy: Use new graph query endpoints (Phase 3)
Step 3: Testing Strategy
- Unit tests: Update Node model tests to remove field assertions
- Integration tests: Verify edge creation still works without returning parent_id
- UI tests: Ensure components render correctly with context-based parents
- Manual testing:
- Create nodes under date pages
- Convert text → task (type changes preserve hierarchy)
- Verify tasks appear in correct containers
- Check backlinks and mentions still work
Example: Component Migration
Before (using node.parentId):
<script>
export let node: Node;
// Component has no idea what the parent is unless node.parentId exists
$: hasParent = !!node.parentId;
</script>After (using context):
<script>
export let node: Node;
export let parentId: string | null = null; // Passed from parent component
// Parent context is explicit, not embedded in node data
$: hasParent = !!parentId;
</script>Acceptance Criteria
-
parent_idandcontainer_node_idfields removed fromNodestruct (Rust) -
parentIdandcontainerNodeIdfields removed fromNodeinterface (TypeScript) - Backend
get_children()no longer populates these fields - All frontend components use parent context instead of
node.parentId - Node creation still creates
has_childedges correctly - UI correctly displays tasks under date pages
- Type conversion (text → task) preserves hierarchy
- All tests pass
- No regression in node creation, editing, or hierarchy display
Technical Notes
- The
Nodemodel is used across Rust backend, Tauri bindings, and TypeScript frontend - Changes must be coordinated across all three layers
- Parent context is already available in components via
getNodesByContainer(parentId)calls - This is a cleanup/refactor, not a feature - behavior should remain identical from user perspective
Estimated Effort
- Backend changes: 1-2 hours (straightforward field removal)
- Frontend changes: 3-4 hours (updating component patterns)
- Testing: 2 hours (integration and manual testing)
- Total: ~6-8 hours for a junior engineer with guidance
References
- Issue SurrealDB Schema Refactor: Graph-Native Architecture #511: SurrealDB graph-native architecture migration
- File:
packages/core/src/db/surreal_store.rs:1307-1314- Temporary workaround to remove - File:
packages/core/src/db/surreal_store.rs:166-167- HardcodedNonein conversion - Documentation: SurrealDB graph relations - https://surrealdb.com/docs/surrealql/statements/relate
Activity
Fix: Property persistence with manual fetching and parent_id reconstr…
Address code review: Add deprecation warnings, recursive tree query, …
Simplify parent_id comments - remove deprecation language
SurrealDB Schema Refactor: Graph-Native Architecture (#513)
malibio commentedon Nov 16, 2025
Test Baseline (pre-implementation):
Starting implementation on branch: feature/issue-514-remove-parent-id-fields
malibio commentedon Nov 16, 2025
Progress Update - TypeScript/Svelte Frontend Migration (95% Complete)
✅ Completed Work:
parentIdandcontainerNodeIdfromNodeinterfaceparentIdparameter in structural update methodsRoot Cause: When
parentIdprop was removed from base-node-viewer, internal function signatures still expect it. Need to:updateStructuralChangesValidated()signature to not requireparentId📊 Impact Analysis:
🔄 Next Steps:
bun run quality:fixto verify zero errorsparent_id/container_node_idfrom Node struct)Branch:
feature/issue-514-remove-parent-id-fieldsEstimated Time to Complete: 1-2 hours for remaining frontend + 2-3 hours for Rust backend
WIP: Remove parentId/containerNodeId - Frontend 95% Complete
malibio commentedon Nov 16, 2025
WIP Commit Pushed 🚀
Comprehensive handoff commit created:
8fbb6cfChanges: 49 files, +447/-1512 lines
Status: 95% complete, 8 compilation errors remaining
Branch:
feature/issue-514-remove-parent-id-fieldsThe commit message contains:
Next AI agent can: Pull the branch, read the commit message, and pick up exactly where we left off with full context!
malibio commentedon Nov 16, 2025
Session Progress Update - 95% Complete
Status: WIP commit ready, blocked by pre-commit hook. 20 test compilation errors remain (all systematic fixes).
✅ Completed (95%):
Frontend (100% Complete):
Backend (95% Complete):
⏸️ Remaining (5% - ~1 hour):
20 test compilation errors - All follow these patterns:
4 lib errors (must fix first):
Some(parent_id)passed wherejson!({})expected (node_service.rs:2900, 2907)16 test errors:
Warnings to fix:
_)asynckeyword)Next Session Plan:
Fix 4 lib compilation errors (~10 min):
Fix 16 test errors (~20 min):
Fix warnings (~10 min):
asyncfrom synchronous functionsVerify & commit (~20 min):
bun run quality:fixbun run test:allTotal estimated time: ~1 hour
Technical Notes:
The codebase is functionally complete with graph-native architecture:
get_parent()methodFiles ready for review: 28 Rust files modified, net -665 lines (simplified!)
WIP: Remove parentId/containerNodeId - Frontend 95% Complete
Complete removal of parentId/containerNodeId fields
3 remaining items
Remove parent_id/container_node_id from Node API - Complete Graph Mig…
Fix: Remove obsolete parent_id population code after dev3 merge
Address code review: Add documentation and cache warnings
Complete hierarchy migration: remove container concept and use only p…
Complete Hierarchy Migration: Remove Container Concept and Fix All Pa…
SurrealDB Schema Refactor: Graph-Native Architecture (#513)
Remove parent_id/container_node_id from Node API - Complete Graph Mig…
Complete Hierarchy Migration: Remove Container Concept and Fix All Pa…
SurrealDB Schema Refactor: Graph-Native Architecture (#513)
Remove parent_id/container_node_id from Node API - Complete Graph Mig…
Complete Hierarchy Migration: Remove Container Concept and Fix All Pa…
SurrealDB Schema Refactor: Graph-Native Architecture (#513)
Remove parent_id/container_node_id from Node API - Complete Graph Mig…
Complete Hierarchy Migration: Remove Container Concept and Fix All Pa…