Parent Issue
Part of Epic #445: Custom Entity Types - User-Defined Schemas with Natural Language Creation
Problem
The backend currently uses a hardcoded ALLOWED_NODE_TYPES constant that blocks creation of custom entity types:
Current validation (packages/desktop-app/src-tauri/src/constants.rs):
pub const ALLOWED_NODE_TYPES: &[&str] = &[
"text", "header", "task", "date", "code-block", "quote-block", "ordered-list"
];
This prevents users from creating nodes with custom types like "invoice", "customer", "training-session", etc., even though:
- The database schema supports any string as
node_type
- The schema system can define validation for any type
- The frontend plugin system supports dynamic types
Solution
Replace hardcoded validation with schema-based validation:
Before:
fn validate_node_type(node_type: &str) -> Result<(), String> {
if !ALLOWED_NODE_TYPES.contains(&node_type) {
return Err(format!("Only text, task, and date nodes are supported. Got: {}", node_type));
}
Ok(())
}
After:
async fn validate_node_type(node_type: &str, schema_service: &SchemaService) -> Result<(), NodeServiceError> {
// Check if schema exists for this type
match schema_service.get_schema(node_type).await {
Ok(_) => Ok(()),
Err(_) => Err(NodeServiceError::invalid_update(
format!("No schema found for node type: {}. Create a schema first.", node_type)
))
}
}
Implementation Details
Files to Modify
1. Remove constant (packages/desktop-app/src-tauri/src/constants.rs):
- Delete
ALLOWED_NODE_TYPES constant entirely
- Update any documentation referencing this constant
2. Update validation (packages/desktop-app/src-tauri/src/commands/nodes.rs):
- Replace
ALLOWED_NODE_TYPES.contains() checks with schema lookups
- Make validation function
async (requires schema service)
- Update function signatures to accept
SchemaService reference
- Used in:
create_node, create_container_node, update_node, save_node_with_parent
3. Update error messages:
- Change from "Only text, task, and date nodes are supported"
- Change to "No schema found for node type: {}. Create a schema first."
- Add helpful guidance about creating schemas
SchemaService Integration
The schema service already exists at packages/core/src/services/schema_service.rs:
pub async fn get_schema(&self, schema_id: &str) -> Result<SchemaDefinition, NodeServiceError> {
let node = self.node_service.get_node(schema_id).await?;
if node.node_type != "schema" {
return Err(NodeServiceError::invalid_update(...));
}
let schema: SchemaDefinition = serde_json::from_value(node.properties)?;
Ok(schema)
}
Integration approach:
// In nodes.rs command handlers
#[tauri::command]
pub async fn create_node(
state: State<'_, AppState>,
node_type: String,
// ... other params
) -> Result<Node, String> {
// Validate type against schema
validate_node_type(&node_type, &state.schema_service).await
.map_err(|e| e.to_string())?;
// Continue with node creation...
}
Backward Compatibility
Core types (text, task, date, etc.) already have schemas, so validation will pass for them automatically. This change is fully backward compatible.
Acceptance Criteria
Functional Requirements
Technical Requirements
Testing Requirements
Testing Plan
Unit Tests (Rust)
#[tokio::test]
async fn test_validate_existing_schema() {
let schema_service = setup_test_schema_service();
schema_service.create_schema("invoice", fields).await.unwrap();
let result = validate_node_type("invoice", &schema_service).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_validate_missing_schema() {
let schema_service = setup_test_schema_service();
let result = validate_node_type("nonexistent", &schema_service).await;
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("No schema found"));
}
#[tokio::test]
async fn test_core_types_still_work() {
let schema_service = setup_test_schema_service();
for core_type in ["text", "task", "date"] {
let result = validate_node_type(core_type, &schema_service).await;
assert!(result.is_ok(), "Core type {} should be valid", core_type);
}
}
Integration Tests
- Create custom schema via MCP/Tauri command
- Create node with custom type
- Verify node creation succeeds
- Verify properties are stored correctly
Migration Notes
No database migration required - This is purely a validation change. The database schema already supports any string as node_type.
Deployment notes:
- Core schemas must exist before deployment (already present)
- No data migration or backfill needed
- Can be deployed without downtime
Performance Considerations
Schema lookup adds ~1-5ms per validation:
- Acceptable for CRUD operations
- SchemaService can cache schemas in memory
- Future optimization: Cache validation results per type
Optimization opportunity (future enhancement):
struct SchemaValidationCache {
validated_types: HashSet<String>,
last_refresh: Instant,
}
Related Issues
Documentation Updates
Success Metrics
- Zero regressions in core type creation
- Custom types work immediately after schema creation
- Error messages result in <5 support requests
- Validation overhead <10ms (measured via benchmarks)
Labels: foundation, backend, breaking-change-internal, rust
Priority: High (blocks custom entity feature)
Estimated effort: 4-6 hours
Parent Issue
Part of Epic #445: Custom Entity Types - User-Defined Schemas with Natural Language Creation
Problem
The backend currently uses a hardcoded
ALLOWED_NODE_TYPESconstant that blocks creation of custom entity types:Current validation (
packages/desktop-app/src-tauri/src/constants.rs):This prevents users from creating nodes with custom types like "invoice", "customer", "training-session", etc., even though:
node_typeSolution
Replace hardcoded validation with schema-based validation:
Before:
After:
Implementation Details
Files to Modify
1. Remove constant (
packages/desktop-app/src-tauri/src/constants.rs):ALLOWED_NODE_TYPESconstant entirely2. Update validation (
packages/desktop-app/src-tauri/src/commands/nodes.rs):ALLOWED_NODE_TYPES.contains()checks with schema lookupsasync(requires schema service)SchemaServicereferencecreate_node,create_container_node,update_node,save_node_with_parent3. Update error messages:
SchemaService Integration
The schema service already exists at
packages/core/src/services/schema_service.rs:Integration approach:
Backward Compatibility
Core types (text, task, date, etc.) already have schemas, so validation will pass for them automatically. This change is fully backward compatible.
Acceptance Criteria
Functional Requirements
Technical Requirements
ALLOWED_NODE_TYPESconstant removed from codebaseTesting Requirements
Testing Plan
Unit Tests (Rust)
Integration Tests
Migration Notes
No database migration required - This is purely a validation change. The database schema already supports any string as
node_type.Deployment notes:
Performance Considerations
Schema lookup adds ~1-5ms per validation:
Optimization opportunity (future enhancement):
Related Issues
Documentation Updates
Success Metrics
Labels:
foundation,backend,breaking-change-internal,rustPriority: High (blocks custom entity feature)
Estimated effort: 4-6 hours