Technical Documentation
Audience: Backend developers, system architects, AI/code-generation tools
Scope: Algorithm, error handling, event model, integration table, and testing specification
1. Hierarchy Algorithm (Materialized Path)
1.1 Path Format
- Strategy: Materialized Path
- Segment length: 4 characters
- Padding: Zero padded
- Separator:
.
Example:
0001.0003.0012
1.2 Create Algorithm
Case A – Create Root Node
- Query maximum root path:
SELECT MAX(path) FROM operation_units WHERE parent_id IS NULL; - If null → start with
0001 - Else → increment last segment
- Persist new unit with generated path
Case B – Create Child Node
- Lock parent row (
SELECT ... FOR UPDATE) - Query maximum child path under parent:
SELECT MAX(path)
FROM operation_units
WHERE parent_id = :parent_id; - Extract last segment and increment
- Concatenate parent path + new segment
- Persist child
1.3 Move Algorithm
Intent: change_parent_and_recalculate_path
Steps:
- Validate new parent is not descendant of current node
- Validate type compatibility and active status
- Lock subtree root (
SELECT ... FOR UPDATE) - Generate new base path under new parent
- For each descendant:
- Replace old path prefix with new path prefix
- Persist updates in a single transaction
Rollback strategy:
- Any failure triggers full transaction rollback
2. Error Handling & Error Codes
2.1 Error Response Shape
{
"error_code": "CIRCULAR_REFERENCE",
"message": "Parent unit cannot be a descendant of current unit",
"details": {}
}
2.2 Standard Error Codes
| Code | HTTP | Description |
|---|---|---|
| CIRCULAR_REFERENCE | 422 | Parent is a descendant of current node |
| TYPE_INCOMPATIBLE | 422 | Parent–child type not allowed |
| UNIT_INACTIVE | 409 | Operation unit is inactive |
| HAS_ACTIVE_CHILDREN | 409 | Unit has active children |
| HAS_ACTIVE_OWNERS | 409 | Unit still has active owners |
| HAS_ACTIVE_POSITIONS | 409 | Unit still has active positions |
| SOFT_DELETE_REQUIRED | 409 | Must soft-delete before hard delete |
| RELATED_RECORD_EXISTS | 409 | Related records prevent deletion |
| NOT_FOUND | 404 | Operation unit not found |
3. Event Model
3.1 Published Events
| Event Name | Trigger |
|---|---|
| operation_unit.created | After successful creation |
| operation_unit.updated | Attribute update |
| operation_unit.moved | Parent or path change |
| operation_unit.activated | is_active = true |
| operation_unit.deactivated | is_active = false |
| operation_unit.deleted | Soft delete |
3.2 Event Payload Examples
{
"event": "operation_unit.moved",
"payload": {
"id": "uuid",
"old_path": "0001.0002",
"new_path": "0001.0003",
"tenant_id": "uuid",
"occurred_at": "ISO8601"
}
}
Events MUST be published after transaction commit.
4. Integration Table (Cross-Module Usage)
| Module | Integration Purpose | Dependency Type |
|---|---|---|
| Employees | Assign owners to units | Foreign key |
| Job Positions | Assign positions | Foreign key |
| Approval Engine | Hierarchical approval | Read-only |
| Authorization | Scope & access control | Read-only |
| Reporting | Aggregation by hierarchy | Read-only |
5. Testing Specification
5.1 Unit Tests
- Path generation for root and child
- Increment logic correctness
- Type compatibility validation
- Error code mapping
5.2 Integration Tests
- Create deep hierarchy (≥5 levels)
- Move node with descendants
- Soft delete with active dependencies
- Hard delete after soft delete
5.3 Edge Case Tests
- Concurrent child creation under same parent
- Move node to same parent (no-op)
- Attempt circular move
- Deactivate node with active children
5.4 Performance Tests
- Tree listing with ≥10,000 nodes
- Path prefix query latency
- Bulk move operation timing
6. Developer Notes
- All hierarchy mutations MUST be transactional
pathcolumn MUST be indexed- Avoid recursive queries in application logic
- Prefer event-driven propagation for downstream modules
WARNING — Row Level Security (RLS)
This project enforces RLS for tenant isolation. When writing code that accesses or mutates tenant-scoped tables:
- Always obtain a tenant-scoped client/context before querying or mutating data; do NOT assume manual
tenant_idfilters are sufficient.- Never perform admin/cross-tenant operations without strict authorization checks; accidental use of a non-scoped client can expose or modify data across tenants.
- For transactional work spanning multiple models, create the tenant-scoped client once and reuse it for the whole transaction to avoid context leakage.
- Validate
tenant_idfrom authenticated user/session and fail fast if missing — do not accept tenant identifiers from untrusted request input.Breaking these rules can cause silent data leakage or RLS policy violations. If unsure, consult
docs/RLS-USAGE-GUIDE.md.
Summary
This document defines the technical contract for the Operation Units Module. It standardizes hierarchy algorithms, error behavior, events, integrations, and testing expectations to ensure consistency, scalability, and safe AI-driven code generation across the system.