non-linear-docs/glossary-and-desicions.md

5.2 KiB

Non-Linear: Glossary & Key Decisions

Glossary

Term Definition
Node / Issue The atomic unit. A single item in the tracker. Untyped — its abstraction level is determined by tree depth.
Decomposition Tree The strict parent→child hierarchy. The structural spine of a project. Every node has one parent (except roots).
Lateral Link A typed edge between two nodes that doesn't affect hierarchy. Types: blocks, relates_to, duplicates.
Layered Overview The primary graph view showing nodes arranged in rows by tree depth.
Focus Widget The detail view showing one node with its parent and children.
Actor Any entity that can perform actions: a human user or an AI agent.
Policy A single permission rule: actor + action + resource scope + effect (allow/deny).
Role A named, reusable bundle of policies. Convenience layer over the granular engine.
Resource Scope Where a policy applies: global (whole project), subtree (node + descendants), or single node.
Subtree A node and all of its descendants in the decomposition tree.
Reparenting Moving a node to a different parent. A structural change that affects permissions.
Opaque Link When a lateral link's target is outside the actor's permission scope. The link is visible but the target's details are withheld.
Root Node The top-level node of a project's decomposition tree. Created automatically with the project.
Depth A node's distance from the root in the decomposition tree. Root = 0, its children = 1, etc.

Key Architectural Decisions

1. Two Separate Graphs

Decision: The decomposition tree and the association graph are explicitly separated, not unified into a single "links with types" model.

Rationale: Jira unifies parent/child and other link types into one system, which makes neither clean. Separating them means:

  • The tree is always a valid hierarchy (one parent per node, no cycles)
  • Reparenting is a distinct, high-privilege operation
  • The layered view derives directly from tree structure
  • Lateral links can be freely added/removed without structural impact

2. Untyped Nodes (Depth = Type)

Decision: Issues have no explicit type field (epic, story, task). Tree depth implies abstraction level.

Rationale: Explicit types create rigidity. Teams argue about whether something is a "story" or a "task." Refactoring hierarchy means changing types manually. With depth-as-type, moving a node automatically changes its conceptual level. Labels handle all orthogonal classification.

Trade-off: The layered view can't use type-specific icons or colors by default. Solved by using depth-based visual styling (bolder at depth 0, lighter at depth 3+).

3. Granular Policies from Day One

Decision: Build the full policy engine (actor + action + resource scope) in v0.1, not bolt it on later.

Rationale: The agent story requires fine-grained, resource-scoped permissions. If we start with coarse RBAC and refine later, every integration and agent needs to be updated. Building granular-first means the agent API is permission-aware from the start. Roles (presets) make it simple for users who don't need custom policies.

Trade-off: More engineering effort upfront. Mitigated by shipping only 3 default presets with minimal custom-role UI.

4. Resource Scope = Graph Position

Decision: Permissions scope to subtrees in the decomposition tree, not to arbitrary resource groups.

Rationale: The graph is the namespace. "Backend API subtree" is a natural, intuitive boundary. No need for a separate resource-naming scheme like ARN paths. This makes permission management visual — you can see permission boundaries on the graph.

Trade-off: Reparenting has permission side effects. Requires warnings and potentially confirmation flows.

Decision: When an actor can see node A but not node B, and there's a link A→B, the actor sees the link exists (and its type) but cannot read B's details.

Rationale: Agents need to know about blockers even if they can't access the blocking node's details. "Something in the Frontend subtree is blocking your task" is useful information. Hiding the link entirely would make agents unable to reason about cross-boundary dependencies.

Trade-off: The existence of a link reveals that a node exists in another subtree, which is a minor information leak. Acceptable for most team contexts.

6. Default Deny

Decision: If no policy explicitly allows an action, it is denied.

Rationale: Safer default, especially with agents. A misconfigured agent that's missing an allow policy does nothing (safe). A misconfigured agent in a default-allow system could do anything (dangerous).

7. Agents as First-Class Actors

Decision: Agents have their own accounts, not shared human credentials. They appear in assignee lists, comment histories, and audit logs with their own identity.

Rationale: Traceability. If an agent changes status on 50 nodes, the audit log shows "deploy-bot changed status" not "John (via script) changed status." This matters for trust and debugging.