Skip to main content

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

  1. Query maximum root path:
    SELECT MAX(path) FROM operation_units WHERE parent_id IS NULL;
  2. If null → start with 0001
  3. Else → increment last segment
  4. Persist new unit with generated path

Case B – Create Child Node

  1. Lock parent row (SELECT ... FOR UPDATE)
  2. Query maximum child path under parent:
    SELECT MAX(path)
    FROM operation_units
    WHERE parent_id = :parent_id;
  3. Extract last segment and increment
  4. Concatenate parent path + new segment
  5. Persist child

1.3 Move Algorithm

Intent: change_parent_and_recalculate_path

Steps:

  1. Validate new parent is not descendant of current node
  2. Validate type compatibility and active status
  3. Lock subtree root (SELECT ... FOR UPDATE)
  4. Generate new base path under new parent
  5. For each descendant:
    • Replace old path prefix with new path prefix
  6. 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

CodeHTTPDescription
CIRCULAR_REFERENCE422Parent is a descendant of current node
TYPE_INCOMPATIBLE422Parent–child type not allowed
UNIT_INACTIVE409Operation unit is inactive
HAS_ACTIVE_CHILDREN409Unit has active children
HAS_ACTIVE_OWNERS409Unit still has active owners
HAS_ACTIVE_POSITIONS409Unit still has active positions
SOFT_DELETE_REQUIRED409Must soft-delete before hard delete
RELATED_RECORD_EXISTS409Related records prevent deletion
NOT_FOUND404Operation unit not found

3. Event Model

3.1 Published Events

Event NameTrigger
operation_unit.createdAfter successful creation
operation_unit.updatedAttribute update
operation_unit.movedParent or path change
operation_unit.activatedis_active = true
operation_unit.deactivatedis_active = false
operation_unit.deletedSoft 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)

ModuleIntegration PurposeDependency Type
EmployeesAssign owners to unitsForeign key
Job PositionsAssign positionsForeign key
Approval EngineHierarchical approvalRead-only
AuthorizationScope & access controlRead-only
ReportingAggregation by hierarchyRead-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
  • path column 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_id filters 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_id from 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.