70 lines
2.3 KiB
Markdown
70 lines
2.3 KiB
Markdown
# ADR 0001: Universal node tree
|
|
|
|
Status: accepted
|
|
Date: 2026-08-25
|
|
|
|
## Context
|
|
|
|
The physical world does not provide a clean structural boundary between a
|
|
location, a container, and an item. A room contains a shelf, a box contains a
|
|
pen, and a toolbox can both be owned and contain tools. Encoding those words as
|
|
exclusive system types would impose rules that the hierarchy itself does not
|
|
need.
|
|
|
|
The project has no users or persisted data requiring compatibility.
|
|
|
|
## Decision
|
|
|
|
Represent the hierarchy as one rooted tree of universal nodes. Every node can
|
|
have children. The system assigns no structural type or role to a node.
|
|
|
|
The initial persistent model is deliberately small:
|
|
|
|
```text
|
|
Node
|
|
- id
|
|
- lookup_code
|
|
- parent_id
|
|
- name
|
|
- quantity?
|
|
```
|
|
|
|
- `id` is stable and opaque.
|
|
- `lookup_code` is a stable human-enterable key for labels and search; it is
|
|
not the internal identity.
|
|
- `parent_id` points to exactly one parent, except for the root.
|
|
- `name` is required and non-empty.
|
|
- `quantity` is an optional non-negative integer. Missing and zero are distinct.
|
|
- Sibling names may be duplicated; identity and paths never depend on names.
|
|
|
|
The server creates two protected nodes:
|
|
|
|
- `Root` is the sole node without a parent.
|
|
- `Unsorted` is a direct child of Root and acts as the inbox for nodes whose
|
|
placement has not been decided.
|
|
|
|
Root and Unsorted cannot be deleted or moved. Their displayed names are fixed
|
|
for now.
|
|
|
|
Moving a node requires one child-handling mode:
|
|
|
|
- `WITH_SUBTREE`: move the node with all descendants. This is the default.
|
|
- `PROMOTE_CHILDREN`: move the node, reparenting its direct children to the
|
|
node's former parent.
|
|
- `CHILDREN_TO_UNSORTED`: move the node, reparenting its direct children to
|
|
Unsorted.
|
|
|
|
All changes made by one move are atomic. A move that would create a cycle is
|
|
rejected. A node may be deleted only when it is empty; recursive deletion is
|
|
not supported.
|
|
|
|
## Consequences
|
|
|
|
- All clients can render the complete core model as a simple tree.
|
|
- The UI may use familiar words such as room, shelf, or box without making them
|
|
database types.
|
|
- A node can be both something the user owns and something that contains other
|
|
nodes.
|
|
- Stable IDs remain necessary because names can change and repeat.
|
|
- Additional metadata can be introduced without changing the tree abstraction.
|