Files
railiance-fabric/docs/ZoneEntityVisualization.md

333 lines
12 KiB
Markdown

# Zone Entity Visualization
## Intent
The graph explorer currently treats zones as visual overlays derived from node
metadata. That is useful for first orientation, but it keeps zones as a
decoration around an already-laid-out graph. The next step is to make a zone a
first-class visualization entity beside nodes and edges.
A zone is a bounded drawing surface for a subgraph. It is similar to a sheet of
paper or a layer in a graphics application: it decides which graph elements are
drawn inside it, how those elements are laid out, how it stacks with other
zones, and whether it can be collapsed into a representative node.
Zones are view entities. They help the operator inspect the fabric without
changing the underlying fabric graph. A zone can be based on deployment
environment, ownership, tenant boundaries, cost center, access zone, or any
other declared view rule, but those concepts remain distinct from the zone
mechanism itself.
## Core Model
A graph view contains three visible entity classes:
- nodes: fabric entities such as services, hosts, repos, scenarios, or owners
- edges: fabric relationships such as deployment, routing, ownership, policy,
dependency, or evidence links
- zones: visual drawing surfaces that contain a selected subgraph
A zone definition describes how to derive and render one zone. A zone instance
is the result of applying a definition to the current graph, filter state, and
view profile.
Zone definitions should be serializable so they can later live in saved graph
profiles, operator presets, or a dedicated view registry.
## Zone Definition
A zone definition should contain at least these fields:
```yaml
id: prod
label: Production
enabled: true
membership:
mode: include
rules:
- field: deploymentEnvironment
op: equals
value: prod
attraction:
rules:
- edge_type: fabric:serves
direction: both
depth: 1
node_filter:
field: kind
op: in
value: [service, endpoint]
layout:
algorithm: cose
options: {}
presentation:
height: 30
color: "#0f766e"
opacity: 0.16
blur_below: true
collapse:
enabled: true
label: Production Zone
```
The exact schema can evolve, but the responsibilities should stay separate:
- membership chooses seed nodes
- attraction optionally expands the zone from those seeds through selected edge
types and depths
- layout chooses how the zone subgraph is arranged
- presentation chooses how the zone itself is drawn and stacked
- collapse chooses how the zone can become a representative node
## Membership Rules
Membership rules decide which nodes initially belong to a zone. They should be
declarative and inspect node data rather than hard-code UI concepts.
Useful operators:
- `equals`
- `not_equals`
- `in`
- `not_in`
- `exists`
- `missing`
- `matches`
Useful rule composition:
- `all`: every nested rule must match
- `any`: at least one nested rule must match
- `none`: no nested rule may match
The first implementation can support a small subset such as `equals`, `in`,
`exists`, `all`, and `any`, then widen the rule language once saved zone
profiles need it.
## Attraction Rules
Attraction rules allow a zone to pull in additional nodes connected to the seed
set. This is useful when the operator wants a zone to include the services,
routes, machines, or contracts that make the zone understandable, even when
those nodes do not carry the seed attribute themselves.
An attraction rule should define:
- edge type or edge-type pattern
- direction: `out`, `in`, or `both`
- maximum depth
- optional node filter
- optional edge filter
Attraction must be deterministic. Given the same graph and zone definitions, the
same node should land in the same zone every time.
Attraction also needs a conflict policy because a node must not belong to more
than one zone. The recommended first policy is priority by zone height and then
definition order:
1. Seed membership wins over attracted membership.
2. If two zones seed the same node, the conflict is reported and the node is
assigned to the higher zone.
3. If two zones attract the same node, the node is assigned to the higher zone.
4. If height ties, the earlier definition wins.
5. Every conflict is recorded as a view diagnostic.
This keeps the single-zone invariant while making ambiguous rules visible.
## Single-Zone Invariant
A visible node must be assigned to zero or one zone in a given graph view. A node
that belongs to no zone remains on the base canvas.
The invariant is important because zones are meant to behave like drawing
surfaces, not like arbitrary tags. Allowing the same node to appear in multiple
zones would make edge routing, selection, collapse behavior, and interaction
state ambiguous.
The model can still support analytical overlap by reporting diagnostics and by
offering alternative view presets. It should not solve overlap by duplicating
nodes in the same rendered view.
## Zone Layout
Each zone may choose its own layout algorithm for its subgraph. For example:
- deployment zones may use force-directed layout
- ownership zones may use concentric layout
- stage zones may use grid layout
- collapsed or nearly empty zones may use compact deterministic placement
The outer graph layout and the zone subgraph layouts are separate concerns. A
first implementation can keep the current Cytoscape layout for all nodes and
only render zone surfaces around assigned nodes. A later implementation should
introduce a two-phase layout:
1. Place zones and unzoned nodes on the main canvas.
2. Place each zone's assigned subgraph inside that zone using the zone's layout.
This will likely require an internal view model that separates fabric graph data
from rendered graph coordinates.
### Per-Zone Layout Preparation
The current graph explorer should not immediately run independent Cytoscape
layouts inside each zone rectangle. Cytoscape layouts operate on collections in
one coordinate space, while the current zone overlay is a view layer drawn over
the already-laid-out graph. Running nested layouts directly against visible
nodes would make pan/zoom, filters, collapse state, and edge routing fragile.
The safer path is a two-phase view layout:
1. Resolve zones from the current graph and view filters.
2. Place zone containers and unzoned nodes in the global canvas.
3. For each zone, compute local coordinates for its assigned nodes using the
zone's configured layout algorithm.
4. Project local zone coordinates into global graph coordinates.
5. Route internal edges inside the zone and boundary edges through the zone
perimeter or collapsed zone node.
The implementation needs these pieces before per-zone layouts become safe:
- a resolved zone view model that survives filtering and saved profiles;
- a stable assignment invariant so a visible node belongs to no more than one
zone;
- a zone container model with size, position, padding, and height;
- a local coordinate projection layer from zone space to Cytoscape space;
- explicit boundary-edge routing rules;
- collapse state that can replace a zone subgraph with a representative node;
- diagnostics when a configured zone layout cannot be applied.
The present implementation already establishes the first, second, and sixth
pieces. A follow-up should introduce a zone container placement phase before
attempting per-zone node layout. That follow-up can keep Cytoscape as the final
renderer while moving layout decisions into a Fabric-owned view model.
### Stable Zone Containers
The first container implementation keeps zone surfaces as view state keyed by
stable zone id. When a zone first appears, the global graph layout supplies its
initial center. Once created, the container owns the zone surface position while
the global layout continues to arrange the base canvas and unzoned nodes.
Dragging a zone moves the container and its currently assigned visible member
nodes together. Rerunning layout or switching the layout algorithm should keep
the container in its stored graph coordinates and then project the zone's
visible subgraph back into that container.
Container state belongs in saved or copied graph view state, not in the Fabric
payload. It is an operator workspace preference, similar to manual visibility
overrides.
### Context Edges
Display-only context edges are not zone connectivity. Repository `declares`
edges, for example, show which repository declared a node, but they should not
create boundary diagnostics, attraction paths, or collapsed-zone boundary
edges. A host can still show them as explanatory evidence in details, but a
zone boundary should only react to canonical or host-promoted graph
relationships.
## Layer Height And Overlap
Zone presentation includes a height. Height is a visual stacking concept, not a
security or ownership concept.
When zones overlap:
- higher zones should draw above lower zones
- lower zones may be desaturated when covered
- lower zones may be blurred or dimmed when covered
- labels should remain readable where practical
- pointer interaction should prefer the highest visible zone
The implementation should avoid implying that a higher zone is more important.
Height is about rendering order and view ergonomics only.
## Collapse To Zone Node
A zone can optionally collapse into a representative node. Collapsing is a view
operation that preserves graph connectivity:
- nodes inside the zone become hidden from the current view
- the zone node represents the collapsed zone
- edges between inside and outside nodes are reconnected to the zone node
- edges fully inside the zone are hidden or summarized
- expanding restores the original nodes and edges
The collapsed zone node should expose useful summary data:
- contained node count
- contained edge count
- dominant node kinds
- inbound and outbound boundary edge counts
- diagnostics such as membership conflicts
This enables drill-down exploration without destroying the operator's context.
## Hierarchical Zones
The collapse model naturally leads to hierarchical zones. A tenant subfabric may
sit inside a landlord fabric, an access zone may sit inside a deployment
environment, and a cost-center view may cut across both as an alternate profile.
Hierarchy should be introduced carefully:
- parent-child containment must be explicit in the zone definition or derived
from a deterministic rule
- a node still belongs to exactly one visible leaf zone
- collapsing a parent collapses all visible descendants
- cross-boundary edges must remain visible at the collapsed boundary
The first implementation should support flat zones. The data model should avoid
choices that would make hierarchy impossible later.
## Diagnostics
Zones should produce diagnostics because rule-based view construction can hide
important ambiguity.
Useful diagnostics:
- node matched by more than one membership rule
- node attracted by more than one zone
- edge crosses zone boundaries
- zone has no seed nodes
- attraction depth reached limit
- collapsed zone has hidden internal boundary evidence
Diagnostics belong to the visualization layer. They should not mutate the
fabric graph.
## Relationship To Fabric Concepts
Zones are not fabrics, subfabrics, realms, domains, environments, cost centers,
or tenants. A zone is a view mechanism that can visualize those concepts.
Examples:
- a deployment-environment zone groups nodes by `dev-tegwick`, `test`, or `prod`
- a financial fabric zone groups nodes by lord or tenant responsibility
- a cost-center zone groups nodes for accounting analysis
- an access-zone view groups nodes by operational access policy once that
metadata exists
This keeps the graph explorer flexible while preserving the stricter meaning of
fabric boundaries: who pays for, owns, and is responsible for infrastructure.
## Implementation Direction
The recommended path is incremental:
1. Introduce a pure zone resolver that converts graph data and zone definitions
into zone instances, node assignments, edge summaries, and diagnostics.
2. Replace the current hard-coded environment/access overlay derivation with
resolver-backed default zone definitions.
3. Add zone-aware rendering state to the graph explorer UI.
4. Add saved zone profiles once the model is stable.
5. Add collapse-to-zone-node behavior.
6. Add per-zone layout only after the resolver and rendering model are stable.
This order keeps the current useful overlay behavior while moving the engine
toward zones as first-class view entities.